summaryrefslogtreecommitdiffstats
path: root/src/sbefw/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/sbefw/core')
-rw-r--r--src/sbefw/core/Makefile56
-rw-r--r--src/sbefw/core/MakefileSeeprom59
-rw-r--r--src/sbefw/core/assert.h49
-rw-r--r--src/sbefw/core/pk_app_cfg.h143
-rw-r--r--src/sbefw/core/plugins/sbeUserDataParser.C297
-rw-r--r--src/sbefw/core/pool.C65
-rw-r--r--src/sbefw/core/pool.H58
-rw-r--r--src/sbefw/core/sbeFFDC.C274
-rw-r--r--src/sbefw/core/sbeFFDC.H148
-rw-r--r--src/sbefw/core/sbeFFDCType.H108
-rw-r--r--src/sbefw/core/sbeFifoMsgUtils.C401
-rw-r--r--src/sbefw/core/sbeFifoMsgUtils.H149
-rw-r--r--src/sbefw/core/sbeHostMsg.C35
-rw-r--r--src/sbefw/core/sbeHostMsg.H184
-rw-r--r--src/sbefw/core/sbeHostUtils.C323
-rw-r--r--src/sbefw/core/sbeHostUtils.H255
-rw-r--r--src/sbefw/core/sbeMemAccessInterface.C270
-rw-r--r--src/sbefw/core/sbeMemAccessInterface.H182
-rw-r--r--src/sbefw/core/sbeSecureMemRegionManager.C187
-rw-r--r--src/sbefw/core/sbeSecureMemRegionManager.H148
-rw-r--r--src/sbefw/core/sbeSecurity.C157
-rw-r--r--src/sbefw/core/sbeSecurity.H91
-rw-r--r--src/sbefw/core/sbeSpMsg.C36
-rw-r--r--src/sbefw/core/sbeSpMsg.H672
-rw-r--r--src/sbefw/core/sbeTimerSvc.C102
-rw-r--r--src/sbefw/core/sbeTimerSvc.H68
-rw-r--r--src/sbefw/core/sbeXipUtils.H63
-rw-r--r--src/sbefw/core/sbe_host_intf.H135
-rw-r--r--src/sbefw/core/sbe_sp_intf.H521
-rw-r--r--src/sbefw/core/sbecmdCntrlTimer.C144
-rw-r--r--src/sbefw/core/sbecmdCntrlTimer.H45
-rw-r--r--src/sbefw/core/sbecmdcntlinst.C203
-rw-r--r--src/sbefw/core/sbecmdcntlinst.H50
-rw-r--r--src/sbefw/core/sbecmdcntrldmt.C367
-rw-r--r--src/sbefw/core/sbecmdcntrldmt.H67
-rw-r--r--src/sbefw/core/sbecmdfastarray.C145
-rw-r--r--src/sbefw/core/sbecmdfastarray.H51
-rw-r--r--src/sbefw/core/sbecmdgeneric.C532
-rw-r--r--src/sbefw/core/sbecmdgeneric.H166
-rw-r--r--src/sbefw/core/sbecmdiplcontrol.C1715
-rw-r--r--src/sbefw/core/sbecmdiplcontrol.H132
-rw-r--r--src/sbefw/core/sbecmdmemaccess.C799
-rw-r--r--src/sbefw/core/sbecmdmemaccess.H70
-rw-r--r--src/sbefw/core/sbecmdmpipl.C430
-rw-r--r--src/sbefw/core/sbecmdmpipl.H63
-rw-r--r--src/sbefw/core/sbecmdparser.C603
-rw-r--r--src/sbefw/core/sbecmdparser.H135
-rw-r--r--src/sbefw/core/sbecmdprocessor.C397
-rw-r--r--src/sbefw/core/sbecmdreceiver.C308
-rw-r--r--src/sbefw/core/sbecmdregaccess.C281
-rw-r--r--src/sbefw/core/sbecmdregaccess.H56
-rw-r--r--src/sbefw/core/sbecmdringaccess.C361
-rw-r--r--src/sbefw/core/sbecmdringaccess.H71
-rw-r--r--src/sbefw/core/sbecmdscomaccess.C432
-rw-r--r--src/sbefw/core/sbecmdscomaccess.H93
-rw-r--r--src/sbefw/core/sbecmdsram.C299
-rw-r--r--src/sbefw/core/sbecmdsram.H64
-rw-r--r--src/sbefw/core/sbecmdtracearray.C156
-rw-r--r--src/sbefw/core/sbecmdtracearray.H54
-rw-r--r--src/sbefw/core/sbecorefiles.mk60
-rw-r--r--src/sbefw/core/sbecoreseepromfiles.mk34
-rw-r--r--src/sbefw/core/sbeerrorcodes.H49
-rw-r--r--src/sbefw/core/sbeevents.H89
-rw-r--r--src/sbefw/core/sbeexeintf.H235
-rw-r--r--src/sbefw/core/sbefapiutil.C150
-rw-r--r--src/sbefw/core/sbefapiutil.H76
-rw-r--r--src/sbefw/core/sbefifo.H231
-rw-r--r--src/sbefw/core/sbeglobals.C48
-rw-r--r--src/sbefw/core/sbeglobals.H138
-rw-r--r--src/sbefw/core/sbeirq.C316
-rw-r--r--src/sbefw/core/sbeirq.H109
-rw-r--r--src/sbefw/core/sbemain.C341
-rw-r--r--src/sbefw/core/sberegaccess.C356
-rw-r--r--src/sbefw/core/sberegaccess.H302
-rw-r--r--src/sbefw/core/sbescom.C221
-rw-r--r--src/sbefw/core/sbescom.H40
-rw-r--r--src/sbefw/core/sbestates.H63
-rw-r--r--src/sbefw/core/sbetrace.H75
-rw-r--r--src/sbefw/core/sbeutil.C62
-rw-r--r--src/sbefw/core/sbeutil.H197
-rw-r--r--src/sbefw/core/vector397
81 files changed, 17114 insertions, 0 deletions
diff --git a/src/sbefw/core/Makefile b/src/sbefw/core/Makefile
new file mode 100644
index 00000000..3245d86e
--- /dev/null
+++ b/src/sbefw/core/Makefile
@@ -0,0 +1,56 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/sbefw/core/Makefile $
+#
+# OpenPOWER sbe Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+#export P2P_ENABLE = 1
+
+export SUB_OBJDIR = /sbefw/core
+
+include img_defs.mk
+include sbecorefiles.mk
+
+OBJS := $(addprefix $(OBJDIR)/, $(SBECORE_OBJECTS))
+
+libsbecore.a: $(OBJS)
+ $(AR) crs $(OBJDIR)/libsbecore.a $(OBJDIR)/*.o
+
+.PHONY: clean sbecore
+sbecore: $(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/core/MakefileSeeprom b/src/sbefw/core/MakefileSeeprom
new file mode 100644
index 00000000..c2ecf874
--- /dev/null
+++ b/src/sbefw/core/MakefileSeeprom
@@ -0,0 +1,59 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/sbecore/Makefile $
+#
+# OpenPOWER sbe Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# 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/coreseeprom
+
+include img_defs.mk
+include sbecoreseepromfiles.mk
+
+GCC-CFLAGS += -mlongcall
+GCC-DEFS += -D__SBEFW_SEEPROM__=1
+OBJS := $(addprefix $(OBJDIR)/, $(SBECORESEEPROM_OBJECTS))
+
+libsbecoreseeprom.a: $(OBJS)
+ $(AR) crs $(OBJDIR)/libsbecoreseeprom.a $(OBJDIR)/*.o
+
+.PHONY: clean sbecoreseeprom
+sbecoreseeprom: $(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/core/assert.h b/src/sbefw/core/assert.h
new file mode 100644
index 00000000..ad2824b7
--- /dev/null
+++ b/src/sbefw/core/assert.h
@@ -0,0 +1,49 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/assert.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file 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/core/pk_app_cfg.h b/src/sbefw/core/pk_app_cfg.h
new file mode 100644
index 00000000..1e5557de
--- /dev/null
+++ b/src/sbefw/core/pk_app_cfg.h
@@ -0,0 +1,143 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/pk_app_cfg.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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 512
+#endif /*__PK_APP_CFG_H__*/
diff --git a/src/sbefw/core/plugins/sbeUserDataParser.C b/src/sbefw/core/plugins/sbeUserDataParser.C
new file mode 100644
index 00000000..d853a1a6
--- /dev/null
+++ b/src/sbefw/core/plugins/sbeUserDataParser.C
@@ -0,0 +1,297 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/plugins/sbeUserDataParser.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <sstream>
+
+#include <utilfile.H>
+#include <utilmem.H>
+
+#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"
+std::string SBE_SEEPROM_BIN = "sbe_seeprom_DD1.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<void*>(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);
+ i_parser.PrintNumber("FW Commit ID ", "0x%08X",
+ (uint32_t)l_pData.fwCommitID);
+ if(l_pData.ddLevel == SBE_FFDC_DD2)
+ {
+ SBE_SEEPROM_BIN = "sbe_seeprom_DD2.bin";
+ }
+ //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 <sbe seeprom bin file>
+ // -ifs attrdump <attr dump file> 2>&1
+ l_strCmd1 << findSbeFile(P9_XIP_TOOL)
+ << " "
+ << findSbeFile(SBE_SEEPROM_BIN.c_str())
+ << " "
+ << 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 <trace dump file> <trace bin file> 2>&1
+ l_strCmd1 << findSbeFile(PPE2FSP_TOOL)
+ << " "
+ << l_strFile.str().c_str()
+ << " "
+ << SBE_TRACE_BIN
+ << " "
+ << "2>&1";
+
+ // fsp-trace -s <sbe string file> <trace bin file> 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/core/pool.C b/src/sbefw/core/pool.C
new file mode 100644
index 00000000..93c67bb4
--- /dev/null
+++ b/src/sbefw/core/pool.C
@@ -0,0 +1,65 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/pool.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include <stdint.h>
+#include <sbetrace.H>
+#include <stddef.h>
+#include<pool.H>
+#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/core/pool.H b/src/sbefw/core/pool.H
new file mode 100644
index 00000000..325a5aa6
--- /dev/null
+++ b/src/sbefw/core/pool.H
@@ -0,0 +1,58 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/pool.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#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/core/sbeFFDC.C b/src/sbefw/core/sbeFFDC.C
new file mode 100644
index 00000000..affa9656
--- /dev/null
+++ b/src/sbefw/core/sbeFFDC.C
@@ -0,0 +1,274 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeFFDC.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "sbefifo.H"
+#include "sbetrace.H"
+#include "sbe_sp_intf.H"
+#include "sbeFifoMsgUtils.H"
+#include "sberegaccess.H"
+#include "sbeFFDC.H"
+#include "sbe_build_info.H"
+#include "sbeglobals.H"
+#include "sbecmdcntrldmt.H"
+
+void SbeFFDCPackage::updateUserDataHeader(uint32_t i_fieldsConfig)
+{
+ //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);
+ }
+ }
+}
+
+uint32_t SbeFFDCPackage::collectAsyncHwpFfdc (void)
+{
+ #define SBE_FUNC "collectAsyncHwpFfdc"
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+
+ switch (SBE_GLOBAL->asyncFfdcRC)
+ {
+ case fapi2::RC_CHECK_MASTER_STOP15_DEADMAN_TIMEOUT:
+ case fapi2::RC_CHECK_MASTER_STOP15_INVALID_STATE:
+ case fapi2::RC_BLOCK_WAKEUP_INTR_CHECK_FAIL:
+ SBE_INFO (SBE_FUNC "Collecting DMT Async FFDC for RC 0x%08x",
+ SBE_GLOBAL->asyncFfdcRC);
+ l_rc = sbeCollectDeadmanFfdc ();
+ break;
+ default:
+ SBE_INFO (SBE_FUNC"No specific Async FFDC to collect");
+ break;
+ }
+
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+uint32_t SbeFFDCPackage::sendOverFIFO(const sbeRespGenHdr_t &i_hdr,
+ const uint32_t i_fieldsConfig,
+ uint32_t &o_bytesSent,
+ const bool i_skipffdcBitCheck)
+{
+ #define SBE_FUNC "sendOverFIFO"
+ 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(!i_skipffdcBitCheck &&
+ (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_hdr.primaryStatus;
+ iv_sbeFFDCDataHeader.secondaryStatus = i_hdr.secondaryStatus;
+ iv_sbeFFDCDataHeader.fwCommitID = SBE_COMMIT_ID;
+#ifdef DD1
+ iv_sbeFFDCDataHeader.ddLevel = SBE_FFDC_DD1;
+#endif
+#ifdef DD2
+ iv_sbeFFDCDataHeader.ddLevel = SBE_FFDC_DD2;
+#endif
+ // Set failed command information
+ // Sequence Id is 0 by default for Fifo interface
+ iv_sbeFFDCHeader.setCmdInfo(0, i_hdr.cmdClass, i_hdr.command);
+ //Update the user data header with dump fields configuration
+ updateUserDataHeader(i_fieldsConfig);
+
+ //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
+}
+
+uint32_t SbeFFDCPackage::sendOverHostIntf(const sbeSbe2PsuRespHdr_t &i_hdr,
+ const uint32_t i_fieldsConfig,
+ sbeMemAccessInterface *i_pMemInterface,
+ uint32_t i_allocatedSize,
+ const bool i_skipffdcBitCheck)
+{
+ #define SBE_FUNC "sendOverHostIntf"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t length = 0;
+ bool isLastAccess = false;
+ fapi2::ReturnCode fapiRc = fapi2::FAPI2_RC_SUCCESS;
+
+ do
+ {
+ //check if SBE internal FFDC should be generated
+ if(!i_skipffdcBitCheck &&
+ (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_hdr.primStatus;
+ iv_sbeFFDCDataHeader.secondaryStatus = i_hdr.secStatus;
+ iv_sbeFFDCDataHeader.fwCommitID = SBE_COMMIT_ID;
+ // Set failed command information
+ iv_sbeFFDCHeader.setCmdInfo(i_hdr.seqID, i_hdr.cmdClass, i_hdr.command);
+ //Update the user data header with dump fields configuration
+ updateUserDataHeader(i_fieldsConfig);
+
+ //Send FFDC package header
+ length = sizeof(iv_sbeFFDCHeader);
+ MEM_AVAILABLE_CHECK(i_allocatedSize, length, isLastAccess);
+ fapiRc = i_pMemInterface->accessWithBuffer(&iv_sbeFFDCHeader, length,
+ isLastAccess);
+ if(fapiRc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ rc = SBE_SEC_GENERIC_FAILURE_IN_EXECUTION;
+ break;
+ }
+
+ //Send FFDC user data header
+ length = sizeof(iv_sbeFFDCDataHeader);
+ MEM_AVAILABLE_CHECK(i_allocatedSize, length, isLastAccess);
+ fapiRc = i_pMemInterface->accessWithBuffer(&iv_sbeFFDCDataHeader,
+ length,
+ isLastAccess);
+ if(fapiRc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ rc = SBE_SEC_GENERIC_FAILURE_IN_EXECUTION;
+ break;
+ }
+
+ //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);
+ MEM_AVAILABLE_CHECK(i_allocatedSize, length, isLastAccess);
+ fapiRc = i_pMemInterface->accessWithBuffer(
+ &sbeFFDCUserData.userDataId,
+ length,
+ isLastAccess);
+ if(fapiRc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ rc = SBE_SEC_GENERIC_FAILURE_IN_EXECUTION;
+ break;
+ }
+
+ //Send User data
+ length = sbeFFDCUserData.userDataId.fieldLen;
+ MEM_AVAILABLE_CHECK(i_allocatedSize, length, isLastAccess);
+ isLastAccess = isLastAccess ||
+ (&sbeFFDCUserData ==
+ &sbeFFDCUserDataArray[NUM_USER_DATA_ELE-1]);
+ fapiRc = i_pMemInterface->accessWithBuffer(
+ sbeFFDCUserData.userDataPtr,
+ length,
+ isLastAccess);
+ if(fapiRc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ rc = SBE_SEC_GENERIC_FAILURE_IN_EXECUTION;
+ break;
+ }
+ }
+ }
+ } while(false);
+ SBE_INFO(SBE_FUNC" [%d] bytes sent",
+ SBE_GLOBAL->hostFFDCAddr.size - i_allocatedSize);
+
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+ #undef SBE_FUNC
+}
diff --git a/src/sbefw/core/sbeFFDC.H b/src/sbefw/core/sbeFFDC.H
new file mode 100644
index 00000000..2487a1f5
--- /dev/null
+++ b/src/sbefw/core/sbeFFDC.H
@@ -0,0 +1,148 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeFFDC.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#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"
+#include "sbeHostUtils.H"
+#include "sbeMemAccessInterface.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,
+ },
+ };
+
+#define NUM_USER_DATA_ELE (sizeof(sbeFFDCUserDataArray)/sizeof(sbeFFDCUserData_t))
+
+//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;
+
+ /*
+ * @bried updateUserDataHeader - method to update user data fields
+ * based on input config
+ *
+ * @param[in] i_fieldsConfig - input fields configuration
+ */
+ void updateUserDataHeader(uint32_t i_fieldsConfig);
+
+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.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 collectAsyncHwpFfdc - method to check and force collect
+ * HWP FFDC to SBE global FFDC region,
+ * asynchronous to the HWP execution
+ * @return - SBE secondary RC
+ */
+ uint32_t collectAsyncHwpFfdc (void);
+
+ /*
+ * @brief sendOverFIFO - method to pack and send SBE internal FFDC
+ * only if isSendInternalFFDCSet() is true
+ * over FIFO interface
+ * @param[in] i_hdr - Fifo response header
+ * @param[in] i_fieldsConfig - bitmap indicating the field
+ * to be sent in FFDC
+ * @param[out] o_bytesSent - number of bytes sent
+ * @param[in] i_skipffdcBitCheck - Boolean to indicate whether
+ * ffdc bit should be checked or not.
+ * By default it is false.
+ *
+ * @return - SBE secondary RC
+ */
+ uint32_t sendOverFIFO(const sbeRespGenHdr_t &i_hdr,
+ const uint32_t i_fieldsConfig,
+ uint32_t &o_bytesSent,
+ const bool i_skipffdcBitCheck = false);
+
+ /* @brief sendOverHostIntf - method to pack and send SBE internal FFDC
+ * only if isSendInternalFFDCSet() is true
+ * over HOST interface
+ *
+ * @param[in] i_hdr - Host response header
+ * @param[in] i_fieldsConfig - bitmap indicating the field
+ * to be sent in FFDC
+ * @param[in] i_pMemInterface - pointer to memory interface object
+ * @param[in] i_allocatedSize - size allocated for FFDC
+ * @param[in] i_skipffdcBitCheck - Boolean to indicate whether
+ * ffdc bit should be checked or not.
+ * By default it is false.
+ *
+ * @return - SBE secondary RC
+ */
+ uint32_t sendOverHostIntf(const sbeSbe2PsuRespHdr_t &i_hdr,
+ const uint32_t i_fieldsConfig,
+ sbeMemAccessInterface *i_pMemInterface,
+ uint32_t i_allocatedSize,
+ const bool i_skipffdcBitCheck = false);
+};
+
+#endif //__SBE_FFDC_H
diff --git a/src/sbefw/core/sbeFFDCType.H b/src/sbefw/core/sbeFFDCType.H
new file mode 100644
index 00000000..b32f4d8e
--- /dev/null
+++ b/src/sbefw/core/sbeFFDCType.H
@@ -0,0 +1,108 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeFFDCType.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#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
+
+enum SBE_FFDC_DD_LEVEL
+{
+ SBE_FFDC_DD1 = 0,
+ SBE_FFDC_DD2 = 1
+};
+
+/* 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
+ uint32_t fwCommitID;// FW commit ID
+ uint32_t ddLevel;// DD level of the SBE
+ sbeFFDCDumpFields_t dumpFields;//bitmapped dumpFields
+} sbeFFDCDataHeader_t;
+
+#endif //__SBE_FFDC_TYPE_H
diff --git a/src/sbefw/core/sbeFifoMsgUtils.C b/src/sbefw/core/sbeFifoMsgUtils.C
new file mode 100644
index 00000000..41d2ca20
--- /dev/null
+++ b/src/sbefw/core/sbeFifoMsgUtils.C
@@ -0,0 +1,401 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeFifoMsgUtils.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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 "plat_hw_access.H"
+#include "assert.h"
+#include "sbeFFDC.H"
+#include "hwp_error_info.H"
+#include "sbeglobals.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;
+
+using namespace fapi2;
+inline uint32_t sbeBuildRespHeaderStatusWordGlobal (void)
+{
+ return ( (((uint32_t)SBE_GLOBAL->sbeCmdRespHdr.prim_status)<<16) |
+ (SBE_GLOBAL->sbeCmdRespHdr.sec_status) );
+}
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+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<uint64_t*>(&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, "
+ "fifo_data:0x%08X, status:0x%08X",
+ l_data.fifo_data, l_data.status);
+
+ // 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) )
+ {
+ SBE_ERROR(SBE_FUNC" Actual length:0x%08X Expected len:0x%08X",
+ l_len, io_len );
+ 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;
+ }
+
+ // Check valid flag
+ if ( !l_data.statusOrReserved.valid_flag )
+ {
+ if( l_data.statusOrReserved.parity_err )
+ {
+ SBE_ERROR(SBE_FUNC"Parity error while reading FIFO."
+ " FIFO status: 0x%08X");
+ l_rc = SBE_SEC_FIFO_PARITY_ERROR;
+ break;
+ }
+ // We can reach here because FIFO was empty. We can not trust
+ // empty flag because empty flag tells the status of FIFO after
+ // operation not at the time of operation
+ if( SBE::isSimicsRunning() )
+ {
+ // sleep if simics is running. Otherwise simics becomes
+ // 99 % busy and fsp does not get a chance to do operation
+ // over FIFO.
+ 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<uint64_t *>(&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
+ if( SBE::isSimicsRunning() )
+ {
+ // sleep if simics is running. Otherwise simics becomes
+ // 99 % busy and fsp does not get a chance to do operation
+ // over FIFO.
+ 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<uint64_t*>(&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<io_len);
+
+ io_len = l_len;
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////
+uint32_t sbeDownFifoSignalEot (void)
+{
+ uint32_t l_rc = 0;
+ #define SBE_FUNC "sbeDownFifoSignalEot "
+ SBE_ENTER(SBE_FUNC);
+ sbeDownFifoStatusReg_t l_status = {0};
+ do
+ {
+ // Read the down stream FIFO status
+ l_rc = sbeDownFifoGetStatus (reinterpret_cast<uint64_t *>(&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)
+ {
+ if( SBE::isSimicsRunning() )
+ {
+ // sleep if simics is running. Otherwise simics becomes
+ // 99 % busy and fsp does not get a chance to do operation
+ // over FIFO.
+ 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,
+ sbeResponseFfdc_t *i_ffdc )
+{
+ #define SBE_FUNC "sbeDsSendRespHdr "
+ 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 != NULL) && (i_ffdc->getRc() != FAPI2_RC_SUCCESS))
+ {
+ SBE_ERROR( SBE_FUNC" FAPI RC:0x%08X", i_ffdc->getRc());
+ // making sure ffdc length is multiples of uint32_t
+ assert((g_FfdcData.ffdcLength % sizeof(uint32_t)) == 0);
+ uint32_t ffdcDataLenInWords = g_FfdcData.ffdcLength
+ / sizeof(uint32_t);
+ // Set failed command information
+ // Sequence Id is 0 by default for Fifo interface
+ i_ffdc->setCmdInfo(0, i_hdr.cmdClass, i_hdr.command);
+ // Add HWP specific ffdc data length
+ i_ffdc->lenInWords += ffdcDataLenInWords;
+ len = sizeof(sbeResponseFfdc_t)/sizeof(uint32_t);
+ rc = sbeDownFifoEnq_mult ( len, ( uint32_t *) i_ffdc);
+ if (rc)
+ {
+ break;
+ }
+ distance += len;
+
+ // Send HWP ffdc data
+ rc = sbeDownFifoEnq_mult ( ffdcDataLenInWords,
+ ( uint32_t *) &g_FfdcData.ffdcData);
+ if (rc)
+ {
+ break;
+ }
+ distance += ffdcDataLenInWords;
+ }
+
+ // If there is a SBE internal failure
+ if((i_hdr.primaryStatus != SBE_PRI_OPERATION_SUCCESSFUL) ||\
+ (i_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL))
+ {
+ SBE_ERROR( SBE_FUNC" primaryStatus:0x%08X secondaryStatus:0x%08X",
+ (uint32_t)i_hdr.primaryStatus,
+ (uint32_t)i_hdr.secondaryStatus);
+
+ //Add FFDC data as well.
+ //Generate all the fields of FFDC package
+ SbeFFDCPackage sbeFfdc;
+ rc = sbeFfdc.sendOverFIFO(i_hdr,
+ 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;
+ #undef SBE_FUNC
+}
diff --git a/src/sbefw/core/sbeFifoMsgUtils.H b/src/sbefw/core/sbeFifoMsgUtils.H
new file mode 100644
index 00000000..214b65e5
--- /dev/null
+++ b/src/sbefw/core/sbeFifoMsgUtils.H
@@ -0,0 +1,149 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeFifoMsgUtils.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbeFifoMsgUtils.H
+ *
+ * @brief This file contains the SBE FIFO Access Common Utility Functions
+ *
+ */
+
+#ifndef __SBEFW_SBEFIFOMSGUTILS_H
+#define __SBEFW_SBEFIFOMSGUTILS_H
+
+#include <stdint.h>
+#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 sbeBuildRespHeaderStatusWordGlobal
+ * Builds the status header word from global variables
+ *
+ * @return Returns the status word in the response header
+ *
+ */
+extern inline uint32_t sbeBuildRespHeaderStatusWordGlobal (void);
+
+/**
+ * @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 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 Pointer to FFDC object, if NULL FFDC package
+ * is not sent in the chip op response
+ *
+ * @return Rc from the underlying scom utility
+ */
+uint32_t sbeDsSendRespHdr(const sbeRespGenHdr_t &i_hdr,
+ sbeResponseFfdc_t *i_ffdc=NULL );
+#endif // __SBEFW_SBEFIFOMSGUTILS_H
diff --git a/src/sbefw/core/sbeHostMsg.C b/src/sbefw/core/sbeHostMsg.C
new file mode 100644
index 00000000..46ff5189
--- /dev/null
+++ b/src/sbefw/core/sbeHostMsg.C
@@ -0,0 +1,35 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeHostMsg.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "sbetrace.H"
+#include "sbeHostMsg.H"
+#include "sbeglobals.H"
+
+void sbeSbe2PsuRespHdr_t::init(void)
+{
+ primStatus = SBE_PRI_OPERATION_SUCCESSFUL;
+ secStatus = SBE_SEC_OPERATION_SUCCESSFUL;
+ seqID = SBE_GLOBAL->sbePsu2SbeCmdReqHdr.seqID;
+ cmdClass = SBE_GLOBAL->sbePsu2SbeCmdReqHdr.cmdClass;
+ command = SBE_GLOBAL->sbePsu2SbeCmdReqHdr.command;
+}
diff --git a/src/sbefw/core/sbeHostMsg.H b/src/sbefw/core/sbeHostMsg.H
new file mode 100644
index 00000000..d6bd8576
--- /dev/null
+++ b/src/sbefw/core/sbeHostMsg.H
@@ -0,0 +1,184 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeHostMsg.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbeHostMsg.H
+ *
+ * @brief This file contains the message structures for SBE Host
+ * communication.
+ *
+ */
+
+#ifndef __SBEFW_SBEHOST_MSG_H
+#define __SBEFW_SBEHOST_MSG_H
+
+#include <stdint.h>
+#include "sbe_host_intf.H"
+#include "sbe_sp_intf.H"
+#include "sbe_link.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;
+
+/* @brief Address and size of memory allocated by Host
+ * for FFDC/pass through commands
+ */
+typedef struct
+{
+ uint32_t size;
+ uint64_t addr;
+} sbeHostAddr_t;
+
+/* @brief Set FFDC Address message
+ */
+typedef struct
+{
+ uint64_t ffdcDataSize:32;
+ uint64_t passCmdDataSize:32;
+ uint64_t ffdcAddr;
+ uint64_t passCmdDataAddr;
+
+ void getFFDCAddr(sbeHostAddr_t &i_hostFFDCAddr)
+ {
+ i_hostFFDCAddr.size = ffdcDataSize;
+ i_hostFFDCAddr.addr = ffdcAddr;
+ }
+
+ void getPassThroughCmdAddr(sbeHostAddr_t &i_hostPassCmdAddr)
+ {
+ i_hostPassCmdAddr.size = passCmdDataSize;
+ i_hostPassCmdAddr.addr = passCmdDataAddr;
+ }
+} sbeSetFFDCAddrReq_t;
+
+/* @brief Read SBE MEM structure
+ */
+typedef struct
+{
+ uint64_t offset:32;
+ uint64_t size:32;
+ uint64_t responseAddr;
+
+ // validate request parameters
+ bool validateReq()
+ {
+ // On ppe reading 8 bytes is optimal. So offset
+ // should be multiple of 8.
+ uint32_t const OFFSET_ALLIGNMENT = 8;
+ // As we use PBA operation, size should be multiple
+ // of 128bytes.
+ uint32_t const SIZE_ALLIGNMENT = 128;
+ // There are 4 seeprom devices each of 64KB,
+ // aso there is 1 ecc byte per 8 bytes of data
+ uint32_t const MAX_SEEPROM_SIZE = ((65536 - (65536 % 9)) / 9) * 8 * 4;
+
+ return ( !(( offset % OFFSET_ALLIGNMENT != 0) ||
+ ( size % SIZE_ALLIGNMENT != 0 ) ||
+ ( ( offset + size ) > MAX_SEEPROM_SIZE )) );
+ }
+ // Return effective seeprom address
+ uint64_t * getEffectiveAddr()
+ {
+ return ( uint64_t *)( SBE_SEEPROM_BASE_ORIGIN + offset );
+ }
+} sbeReadMemReq_t;
+
+/*****************************************************************/
+/* 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();
+} sbeSbe2PsuRespHdr_t;
+
+#endif // __SBEFW_SBEHOST_MSG_H
diff --git a/src/sbefw/core/sbeHostUtils.C b/src/sbefw/core/sbeHostUtils.C
new file mode 100644
index 00000000..ea0605a3
--- /dev/null
+++ b/src/sbefw/core/sbeHostUtils.C
@@ -0,0 +1,323 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeHostUtils.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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"
+#include "sbeglobals.H"
+#include "sbeMemAccessInterface.H"
+#include "sbeFFDC.H"
+#include "hwp_error_info.H"
+#include "sberegaccess.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<uint64_t*>(&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 (SBE_GLOBAL->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 (SBE_GLOBAL->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( SBE_GLOBAL->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"
+ SBE_ENTER(SBE_FUNC);
+ do
+ {
+ // Making sure the PSU access utility is functional
+ if(io_rc != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ break;
+ }
+
+ uint32_t l_allocatedSize = SBE_GLOBAL->hostFFDCAddr.size;
+ bool l_is_lastAccess = false;
+ // Default EX Target Init..Not changing it for the time being
+ fapi2::Target<fapi2::TARGET_TYPE_EX> l_ex(
+ fapi2::plat_getTargetHandleByChipletNumber<fapi2::TARGET_TYPE_EX>(
+ sbeMemAccessInterface::PBA_DEFAULT_EX_CHIPLET_ID));
+ p9_PBA_oper_flag l_myPbaFlag;
+ l_myPbaFlag.setOperationType(p9_PBA_oper_flag::INJ);
+
+ sbeMemAccessInterface l_PBAInterface(
+ SBE_MEM_ACCESS_PBA,
+ SBE_GLOBAL->hostFFDCAddr.addr,
+ &l_myPbaFlag,
+ SBE_MEM_ACCESS_WRITE,
+ sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES,
+ l_ex);
+
+ bool l_internal_ffdc_present = ((i_sbe2PsuRespHdr.primStatus !=
+ SBE_PRI_OPERATION_SUCCESSFUL) ||
+ (i_sbe2PsuRespHdr.secStatus !=
+ SBE_SEC_OPERATION_SUCCESSFUL));
+
+ // If no ffdc , exit;
+ sbeResponseFfdc_t l_ffdc;
+ l_ffdc.setRc(i_fapiRc);
+ if(l_ffdc.getRc() != fapi2::FAPI2_RC_SUCCESS)
+ {
+ // Clear global fapi2::current_err so that
+ // FFDC can be sent over PBA interface.
+ // We are good with HWP ffdc, as
+ // g_FfdcData.fapiRc is a copy of current_err
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ i_sbe2PsuRespHdr.setStatus(SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ l_internal_ffdc_present = true;
+
+ SBE_ERROR( SBE_FUNC" FAPI RC:0x%08X", l_ffdc.getRc());
+ SBE_INFO(SBE_FUNC" FFDC memory - addr[0x%08X%08X] size[%d]bytes",
+ static_cast<uint32_t>(SBE::higher32BWord(SBE_GLOBAL->hostFFDCAddr.addr)),
+ static_cast<uint32_t>(SBE::lower32BWord(SBE_GLOBAL->hostFFDCAddr.addr)),
+ SBE_GLOBAL->hostFFDCAddr.size);
+ uint32_t ffdcDataLenInWords = fapi2::g_FfdcData.ffdcLength
+ / sizeof(uint32_t);
+ // Set failed command information
+ l_ffdc.setCmdInfo(i_sbe2PsuRespHdr.seqID,
+ i_sbe2PsuRespHdr.cmdClass,
+ i_sbe2PsuRespHdr.command);
+ // Add HWP specific ffdc data length
+ l_ffdc.lenInWords += ffdcDataLenInWords;
+
+ uint32_t len = sizeof(sbeResponseFfdc_t);
+ MEM_AVAILABLE_CHECK(l_allocatedSize, len, l_is_lastAccess);
+ fapi2::ReturnCode l_fapiRc = l_PBAInterface.accessWithBuffer(
+ &l_ffdc,
+ len,
+ l_is_lastAccess);
+ if(l_fapiRc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ io_rc = SBE_SEC_GENERIC_FAILURE_IN_EXECUTION;
+ break;
+ }
+ MEM_AVAILABLE_CHECK(l_allocatedSize,
+ ffdcDataLenInWords,
+ l_is_lastAccess);
+ l_is_lastAccess = l_is_lastAccess ||
+ !l_internal_ffdc_present ||
+ !SbeRegAccess::theSbeRegAccess().isSendInternalFFDCSet();
+ l_fapiRc = l_PBAInterface.accessWithBuffer(
+ &fapi2::g_FfdcData.ffdcData,
+ ffdcDataLenInWords,
+ l_is_lastAccess);
+ if(l_fapiRc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ io_rc = SBE_SEC_GENERIC_FAILURE_IN_EXECUTION;
+ break;
+ }
+ }
+
+ // Send SBE internal ffdc if there is enough memory allocated
+ if(l_internal_ffdc_present)
+ {
+ SBE_ERROR( SBE_FUNC" primaryStatus:0x%08X secondaryStatus:0x%08X",
+ (uint32_t)i_sbe2PsuRespHdr.primStatus,
+ (uint32_t)i_sbe2PsuRespHdr.secStatus);
+ // SBE internal FFDC package
+ SbeFFDCPackage sbeFfdc;
+ //Generate all the fields of FFDC package
+ io_rc = sbeFfdc.sendOverHostIntf(i_sbe2PsuRespHdr,
+ SBE_FFDC_ALL_DUMP,
+ &l_PBAInterface,
+ l_allocatedSize);
+ if (io_rc)
+ {
+ break;
+ }
+ }
+
+ // 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/core/sbeHostUtils.H b/src/sbefw/core/sbeHostUtils.H
new file mode 100644
index 00000000..3ffa48e1
--- /dev/null
+++ b/src/sbefw/core/sbeHostUtils.H
@@ -0,0 +1,255 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeHostUtils.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbeHostUtils.H
+ *
+ * @brief This file contains basic SBE PSU hardware specific
+ * definitions and operations.
+ *
+ */
+
+#ifndef __SBEFW_SBEHOSTUTILS_H
+#define __SBEFW_SBEHOSTUTILS_H
+
+#include <stdint.h>
+#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,
+
+ // Bit 4 OR flag for SBE->PSU Doorbell Register,
+ // When this is set by SBE, it would trigger an interrupt to host
+ // firmware to inform that Host Pass through command received.
+ SBE_SBE2PSU_DOORBELL_SET_BIT4 = 0x0800000000000000ull,
+
+ // Bit 14 OR flag for SBE->PSU Doorbell Register;
+ // When this is set by SBE, it would trigger an interrupt to host
+ // firmware to inform that timer has expired.
+ SBE_SBE2PSU_DOORBELL_SET_BIT14 = 0x0002000000000000ull,
+
+} 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/core/sbeMemAccessInterface.C b/src/sbefw/core/sbeMemAccessInterface.C
new file mode 100644
index 00000000..bb341f38
--- /dev/null
+++ b/src/sbefw/core/sbeMemAccessInterface.C
@@ -0,0 +1,270 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeMemAccessInterface.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "sbeMemAccessInterface.H"
+
+#ifdef SEEPROM_IMAGE
+// Using Function pointer to force long call
+p9_adu_access_FP_t p9_adu_access_hwp = &p9_adu_access;
+p9_adu_setup_FP_t p9_adu_setup_hwp = &p9_adu_setup;
+#endif
+
+using namespace fapi2;
+
+void MEM_AVAILABLE_CHECK(uint32_t &io_available_len,uint32_t &io_len_to_send,bool &io_is_last_access)
+{
+ if(io_len_to_send > io_available_len)
+ {
+ SBE_INFO(SBE_FUNC" Allocated memory is less, truncating the access");
+ io_len_to_send = io_available_len;
+ io_is_last_access = true;
+ }
+ io_available_len -= io_len_to_send;
+}
+
+ReturnCode sbeMemAccessInterface::setup()
+{
+#define SBE_FUNC "sbeMemAccessInterface::setup"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode fapiRc = FAPI2_RC_SUCCESS;
+
+ // Reset the current granule count
+ iv_currGranule = 0;
+ iv_intfCleanedUp = false;
+ SBE_INFO("iv_addr [0x%08x%08x]", SBE::higher32BWord(iv_addr), SBE::lower32BWord(iv_addr));
+ if(iv_interface == SBE_MEM_ACCESS_PBA)
+ {
+ // Call the PBA setup HWP
+ SBE_EXEC_HWP(fapiRc,
+ p9_pba_setup,
+ plat_getChipTarget(),
+ iv_ex,
+ iv_addr,
+ (iv_mode == SBE_MEM_ACCESS_READ),
+ ((p9_PBA_oper_flag*)iv_flags)->setFlag(),
+ iv_maxGranule);
+ }
+ if(iv_interface == SBE_MEM_ACCESS_ADU)
+ {
+ // Call the ADU setup HWP
+ SBE_EXEC_HWP(fapiRc,
+ p9_adu_setup_hwp,
+ plat_getChipTarget(),
+ iv_addr,
+ (iv_mode == SBE_MEM_ACCESS_READ),
+ ((p9_ADU_oper_flag*)iv_flags)->setFlag(),
+ iv_maxGranule)
+ }
+ // if setup returns error
+ if(fapiRc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC" setup Failed");
+ }
+ else
+ {
+ // Assumption is Hwp won't return zero for Num Granules
+ assert(0 != iv_maxGranule);
+
+ SBE_INFO(SBE_FUNC "Hwp returned iv_maxGranule=[0x%08X]",
+ iv_maxGranule);
+ }
+ return fapiRc;
+#undef SBE_FUNC
+}
+
+ReturnCode sbeMemAccessInterface::accessGranule(const bool i_isLastAccess)
+{
+#define SBE_FUNC "sbeMemAccessInterface::accessGranule"
+ SBE_DEBUG(SBE_FUNC);
+ ReturnCode fapiRc = FAPI2_RC_SUCCESS;
+
+ do
+ {
+ // Check if we need to do a setup before access
+ if(iv_intfCleanedUp)
+ {
+ fapiRc = setup();
+ // if setup returns error
+ if( fapiRc != FAPI2_RC_SUCCESS )
+ {
+ break;
+ }
+ }
+ iv_intfCleanedUp = (i_isLastAccess || (iv_maxGranule == 1));
+ if(iv_interface == SBE_MEM_ACCESS_PBA)
+ {
+ // Call PBA access for read/write
+ SBE_EXEC_HWP(fapiRc,
+ p9_pba_access,
+ plat_getChipTarget(),
+ iv_addr,
+ (iv_mode == SBE_MEM_ACCESS_READ),
+ ((p9_PBA_oper_flag*)iv_flags)->setFlag(),
+ (iv_currGranule == 0),
+ iv_intfCleanedUp,
+ (uint8_t *)&iv_buffer);
+ }
+ if(iv_interface == SBE_MEM_ACCESS_ADU)
+ {
+ // Call ADU access HWP for ADU write/read request
+ SBE_EXEC_HWP(fapiRc,
+ p9_adu_access_hwp,
+ plat_getChipTarget(),
+ iv_addr,
+ (iv_mode == SBE_MEM_ACCESS_READ),
+ ((p9_ADU_oper_flag*)iv_flags)->setFlag(),
+ (iv_currGranule == 0),
+ iv_intfCleanedUp,
+ (uint8_t *)&iv_buffer)
+ }
+ if(fapiRc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC" access HWP failed");
+ break;
+ }
+ iv_maxGranule--;
+ iv_currGranule++;
+ // Advance the address
+ iv_addr += iv_granuleSize;
+ iv_iterator = (iv_mode == SBE_MEM_ACCESS_READ)?
+ iv_granuleSize : 0;
+ } while(false);
+
+ return fapiRc;
+#undef SBE_FUNC
+}
+
+ReturnCode sbeMemAccessInterface::accessWithBuffer(const void *io_buffer,
+ const uint32_t i_len,
+ const bool i_isLastAccess)
+{
+#define SBE_FUNC "sbeMemAccessInterface::accessWithBuffer"
+ SBE_DEBUG(SBE_FUNC" len[%d]",i_len);
+ ReturnCode fapiRc = FAPI2_RC_SUCCESS;
+ uint32_t iterator = 0;
+ bool is_lastGranule = false;
+
+ do
+ {
+ if(iv_mode == SBE_MEM_ACCESS_WRITE)
+ {
+ // Fill buffer
+ while((iv_iterator < iv_granuleSize) && (iterator < i_len))
+ {
+ iv_buffer[iv_iterator++] = ((char*)io_buffer)[iterator++];
+ }
+ // If Adu, put the ecc and itag applicable bytes
+ if(iv_interface == SBE_MEM_ACCESS_ADU)
+ {
+ if(((p9_ADU_oper_flag*)iv_flags)->getEccMode())
+ {
+ iv_buffer[iv_iterator++] = ((char*)io_buffer)[iterator++];
+ }
+ if(((p9_ADU_oper_flag*)iv_flags)->getItagMode())
+ {
+ iv_buffer[iv_iterator++] = ((char*)io_buffer)[iterator++];
+ }
+ }
+ }
+
+ if(i_isLastAccess)
+ {
+ if((iv_mode == SBE_MEM_ACCESS_WRITE) &&
+ (iterator >= i_len))
+ {
+ is_lastGranule = true;
+ alignAccessWithBuffer();
+ }
+ else if((iv_mode == SBE_MEM_ACCESS_READ) &&
+ ((i_len - iterator) <= iv_granuleSize))
+ {
+ is_lastGranule = true;
+ iv_iterator = 0;
+ }
+ }
+ if(((iv_mode == SBE_MEM_ACCESS_WRITE) &&
+ (iv_iterator >= iv_granuleSize))
+ ||
+ ((iv_mode == SBE_MEM_ACCESS_READ) &&
+ (iv_iterator == 0)))
+ {
+ fapiRc = accessGranule(is_lastGranule);
+ // Break out on error
+ if(fapiRc != FAPI2_RC_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ if(iv_mode == SBE_MEM_ACCESS_READ)
+ {
+ // Fill the buffer
+ while((iv_iterator > 0) && (iterator < i_len))
+ {
+ ((char*)io_buffer)[iterator++] =
+ iv_buffer[iv_granuleSize - iv_iterator];
+ iv_iterator--;
+ }
+ // If Adu, get the ecc and itag applicable bytes
+ if(iv_interface == SBE_MEM_ACCESS_ADU)
+ {
+ uint32_t index = iv_granuleSize;
+ if(((p9_ADU_oper_flag*)iv_flags)->getEccMode())
+ {
+ ((char*)io_buffer)[iterator++] =
+ iv_buffer[index++];
+ }
+ if(((p9_ADU_oper_flag*)iv_flags)->getItagMode())
+ {
+ ((char*)io_buffer)[iterator++] =
+ iv_buffer[index];
+ }
+ }
+ }
+
+ // data is completely processed
+ if(iterator >= i_len)
+ {
+ break;
+ }
+ } while(true);
+
+ return fapiRc;
+#undef SBE_FUNC
+}
+
+void sbeMemAccessInterface::alignAccessWithBuffer()
+{
+#define SBE_FUNC "sbeMemAccessInterface::alignAccessWithBuffer"
+ SBE_DEBUG(SBE_FUNC);
+ // Required to fill zeroes only if the iv_buffer is partially occupied
+ if(iv_iterator != 0)
+ {
+ // zero filling
+ while(iv_iterator < iv_granuleSize)
+ {
+ iv_buffer[iv_iterator++] = 0;
+ }
+ }
+#undef SBE_FUNC
+}
diff --git a/src/sbefw/core/sbeMemAccessInterface.H b/src/sbefw/core/sbeMemAccessInterface.H
new file mode 100644
index 00000000..386eba26
--- /dev/null
+++ b/src/sbefw/core/sbeMemAccessInterface.H
@@ -0,0 +1,182 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeMemAccessInterface.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __SBE_MEM_ACCESS_INTERFACE_H
+#define __SBE_MEM_ACCESS_INTERFACE_H
+
+#include "fapi2.H"
+
+#include "p9_pba_coherent_utils.H"
+#include "p9_pba_setup.H"
+#include "p9_pba_access.H"
+
+#include "p9_adu_setup.H"
+#include "p9_adu_access.H"
+#include "p9_adu_coherent_utils.H"
+
+/* @brief Enum for read or write interface
+ * */
+enum sbeMemAccessMode
+{
+ SBE_MEM_ACCESS_READ = 1,
+ SBE_MEM_ACCESS_WRITE = 2,
+};
+
+/* @brief Enum for PBA or ADU interface
+ * */
+enum sbeMemAccessInterfaceType
+{
+ SBE_MEM_ACCESS_PBA,
+ SBE_MEM_ACCESS_ADU,
+};
+
+// Helper functions
+/*
+ * @brief function to check if the length to send can be
+ * accomodated in the available memory, else make it a last
+ * access on the interface
+ */
+void MEM_AVAILABLE_CHECK(uint32_t &io_available_len,
+ uint32_t &io_len_to_send,
+ bool &io_is_last_access);
+
+class sbeMemAccessInterface
+{
+ private:
+ // Bigger of PBA/ADU granules
+ static constexpr uint32_t MEM_INTERFACE_SIZE_BYTES = 128;
+
+ // Address to start read/write from
+ uint64_t iv_addr;
+ // Interface type - PBA/ADU
+ sbeMemAccessInterfaceType iv_interface;
+ // Pointer to procedure flags - p9_PBA_oper_flag/p9_ADU_oper_flag
+ void *iv_flags;
+ // Read or Write mode
+ sbeMemAccessMode iv_mode;
+ // Ex target used in PBA interface, not applicable for ADU
+ fapi2::Target<fapi2::TARGET_TYPE_EX > iv_ex;
+ // Number of granule that can be sent before calling setup again
+ uint32_t iv_maxGranule;
+ // Iterator to track the current depth of iv_buffer
+ uint32_t iv_iterator;
+ // Number of granules sent after the setup
+ uint32_t iv_currGranule;
+ // Granule size based on interface - PBA/ADU
+ uint32_t iv_granuleSize;
+ // Buffer size is bigger of the two granules
+ char iv_buffer[MEM_INTERFACE_SIZE_BYTES] __attribute__ ((aligned (8)));
+ // Interface cleaned up - indicates if the underlying
+ // HWP cleanup is done for the interface.
+ // A new object assumes interface is in cleaned up
+ // state.
+ // If the interface is in cleaned up state,
+ // next access will happen only after the setup.
+ bool iv_intfCleanedUp;
+
+ /* @brief Wrapper function to call setup procedures
+ * for the interface. This private API is used
+ * internally as per the state of the object,
+ * i.e., whenever the iv_maxGranule
+ * becomes 0, while using interface access APIs
+ *
+ * @return fapi rc
+ */
+ fapi2::ReturnCode setup();
+
+ /* @brief Align and finalize the accessWithBuffer calls - useful in case
+ * the data to be read/written is not aligned to the
+ * granule sizes of the interfaces
+ *
+ * @return fapi rc
+ */
+ void alignAccessWithBuffer();
+
+ public:
+ //Default EX Target ChipletId to be used in PBA by default
+ static constexpr uint32_t PBA_DEFAULT_EX_CHIPLET_ID = 0x20;
+
+ // PBA / ADU Granule size as per the HWP Requirement
+ static constexpr uint32_t PBA_GRAN_SIZE_BYTES = 128;
+ static constexpr uint32_t ADU_GRAN_SIZE_BYTES = 8;
+
+ /* @brief Constructor
+ *
+ * @param[in] i_interface Type of the interface
+ * @param[in] i_addr Address to read/write from
+ * @param[in] i_flags Pointer to PBA/ADU flags
+ * @param[in] i_mode Read/Write mode
+ * @param[in] i_granuleSize Granule size of the interface type
+ * @param[in] i_ex EX target[Optional in case of ADU]
+ */
+ sbeMemAccessInterface(
+ sbeMemAccessInterfaceType i_interface,
+ uint64_t i_addr,
+ void *i_flags,
+ sbeMemAccessMode i_mode,
+ uint32_t i_granuleSize,
+ fapi2::Target<fapi2::TARGET_TYPE_EX> i_ex
+ = fapi2::Target<fapi2::TARGET_TYPE_EX>()):
+ iv_addr(i_addr),
+ iv_interface(i_interface),
+ iv_flags(i_flags),
+ iv_mode(i_mode),
+ iv_ex(i_ex),
+ iv_maxGranule(0),
+ iv_iterator(0),
+ iv_currGranule(0),
+ iv_granuleSize(i_granuleSize),
+ iv_intfCleanedUp(true)
+ {
+ }
+
+ void * getBuffer()
+ {
+ iv_iterator = iv_granuleSize;
+ return &iv_buffer;
+ }
+
+ /* @brief Read/Write a single granule on PBA/ADU interface
+ *
+ * @param[in] i_isLastAccess Should the interface be cleaned up
+ * after this access
+ *
+ * @return fapi rc
+ */
+ fapi2::ReturnCode accessGranule(const bool i_isLastAccess = false);
+
+ /* @brief Read/Write on PBA/ADU interface with the given buffer.
+ *
+ * @param[in] io_buffer Pointer to the data to read/write
+ * @param[in] i_len Length of the data to read/write in bytes
+ * @param[in] i_isLastAccess Should the interface be cleaned up
+ * after this access
+ *
+ * @return fapi rc
+ */
+ fapi2::ReturnCode accessWithBuffer(const void *io_buffer,
+ const uint32_t i_len,
+ const bool i_isLastAccess = false);
+
+};
+#endif //__SBE_MEM_ACCESS_INTERFACE_H
diff --git a/src/sbefw/core/sbeSecureMemRegionManager.C b/src/sbefw/core/sbeSecureMemRegionManager.C
new file mode 100644
index 00000000..ef81ca87
--- /dev/null
+++ b/src/sbefw/core/sbeSecureMemRegionManager.C
@@ -0,0 +1,187 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeSecureMemRegionManager.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "sbeSecureMemRegionManager.H"
+#include "sbetrace.H"
+#include "sbeutil.H"
+#include "sbeglobals.H"
+
+#ifndef __SBEFW_SEEPROM__
+SBESecureMemRegionManager mainStoreSecMemRegionManager(
+ &SBE_GLOBAL->mainMemRegions[0],
+ MAX_MAIN_STORE_REGIONS);
+SBEOccSramSecMemRegionManager occSramSecRegionManager(
+ &SBE_GLOBAL->occSramRegions[0],
+ MAX_OCC_SRAM_REGIONS);
+
+secureMemRegion_t SBESecureMemRegionManager::getPartialRegionSize(
+ const secureMemRegion_t i_region)
+{
+ secureMemRegion_t ret = {};
+ for(size_t i = 0; i < iv_regionsOpenCnt; i++)
+ {
+ uint64_t minStartAddr = i_region.startAddress < iv_memRegions[i].startAddress ?
+ i_region.startAddress : iv_memRegions[i].startAddress;
+ uint64_t iRegionEndAddress = i_region.startAddress + i_region.size - 1;
+ uint64_t existingRegionEndAddress = iv_memRegions[i].startAddress + iv_memRegions[i].size - 1;
+ uint64_t maxEndAddr = iRegionEndAddress >= existingRegionEndAddress ?
+ iRegionEndAddress : existingRegionEndAddress;
+
+ // detect overlap
+ if((maxEndAddr - minStartAddr + 1) < (i_region.size + iv_memRegions[i].size))
+ {
+ ret = iv_memRegions[i];
+ // Give preference to first region
+ if(i_region.startAddress >= iv_memRegions[i].startAddress &&
+ i_region.startAddress < (iv_memRegions[i].startAddress +
+ iv_memRegions[i].size))
+ {
+ // Return the existing window to the extent of input window
+ ret.startAddress = i_region.startAddress;
+ ret.size = iv_memRegions[i].startAddress + iv_memRegions[i].size
+ - i_region.startAddress;
+ if(ret.size > i_region.size)
+ ret.size = i_region.size;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+#endif //__SBEFW_SEEPROM__
+#ifdef __SBEFW_SEEPROM__
+
+// Public functions
+sbeSecondaryResponse SBESecureMemRegionManager::add(const uint64_t i_startAddr,
+ const uint32_t i_size,
+ const uint8_t i_mode)
+{
+ #define SBE_FUNC "SBESecureMemRegionManager::add"
+ sbeSecondaryResponse rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ do
+ {
+ if(getPartialRegionSize({i_startAddr, i_size, i_mode}).mode)
+ {
+ SBE_ERROR(SBE_FUNC" SBE_SEC_MEM_REGION_AMEND_ATTEMPTED");
+ rc = SBE_SEC_MEM_REGION_AMEND_ATTEMPTED;
+ break;
+ }
+ if(iv_regionsOpenCnt >= iv_maxRegions)
+ {
+ SBE_ERROR(SBE_FUNC" SBE_SEC_MAXIMUM_MEM_REGION_EXCEEDED");
+ rc = SBE_SEC_MAXIMUM_MEM_REGION_EXCEEDED;
+ break;
+ }
+ SBE_INFO(SBE_FUNC" Adding region Mem[0x%08X%08X], size[0x%08X]",
+ SBE::higher32BWord(i_startAddr),
+ SBE::lower32BWord(i_startAddr),
+ i_size);
+ iv_memRegions[iv_regionsOpenCnt++] = {i_startAddr, i_size, i_mode};
+ SBE_INFO(SBE_FUNC" after addition iv_regionsOpenCnt [%d]",
+ iv_regionsOpenCnt);
+ } while(0);
+ return rc;
+ #undef SBE_FUNC
+}
+
+sbeSecondaryResponse SBESecureMemRegionManager::remove(const uint64_t i_startAddr)
+{
+ #define SBE_FUNC "SBESecureMemRegionManager::remove";
+ size_t i = 0;
+ sbeSecondaryResponse rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ for(; i < iv_regionsOpenCnt; i++)
+ {
+ if(i_startAddr == iv_memRegions[i].startAddress)
+ {
+ break;
+ }
+ }
+ if(i < iv_regionsOpenCnt)
+ {
+ SBE_INFO(SBE_FUNC" Deleting region i[%d], Mem[0x%08X%08X], size[0x%08X]",
+ i,
+ SBE::higher32BWord(iv_memRegions[i].startAddress),
+ SBE::lower32BWord(iv_memRegions[i].startAddress),
+ iv_memRegions[i].size);
+ // Remove the empty slot and maintain contiguous list
+ for(size_t j = i; j < iv_regionsOpenCnt-1; j++)
+ {
+ iv_memRegions[j].startAddress = iv_memRegions[j+1].startAddress;
+ iv_memRegions[j].size = iv_memRegions[j+1].size;
+ iv_memRegions[j].mode = iv_memRegions[j+1].mode;
+ }
+
+ iv_regionsOpenCnt--;
+ SBE_INFO(SBE_FUNC" After deletion : iv_regionsOpenCnt[%d]", iv_regionsOpenCnt);
+ }
+ else
+ {
+ SBE_ERROR(SBE_FUNC" SBE_SEC_MEM_REGION_NOT_FOUND");
+ rc = SBE_SEC_MEM_REGION_NOT_FOUND;
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
+#endif //__SBEFW_SEEPROM__
+#ifndef __SBEFW_SEEPROM__
+
+sbeSecondaryResponse SBESecureMemRegionManager::isAccessAllowed(
+ secureMemRegion_t i_region)
+{
+ #define SBE_FUNC "SBESecureMemRegionManager::isAccessAllowed"
+ sbeSecondaryResponse rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ if(SBE_GLOBAL->sbeFWSecurityEnabled)
+ {
+ while(i_region.size > 0)
+ {
+ secureMemRegion_t foundregion = getPartialRegionSize(i_region);
+ // Check if the found region has allowable access level
+ // and that the region overlap is from the beginning itself
+ if((i_region.mode & foundregion.mode) &&
+ (i_region.startAddress == foundregion.startAddress))
+ {
+ SBE_INFO(SBE_FUNC" foundRegion Mem[0x%08X%08X], size[0x%08X]",
+ SBE::higher32BWord(foundregion.startAddress),
+ SBE::lower32BWord(foundregion.startAddress),
+ foundregion.size);
+ i_region.size -= foundregion.size;
+ i_region.startAddress += foundregion.size;
+ }
+ else
+ {
+ SBE_ERROR(SBE_FUNC" Non secure access to memory blocked "
+ "Addr[0x%08X%08X] Size[0x%08X]",
+ SBE::higher32BWord(i_region.startAddress),
+ SBE::lower32BWord(i_region.startAddress),
+ i_region.size);
+ rc = SBE_SEC_BLACKLISTED_MEM_ACCESS;
+ break;
+ }
+ }
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+#endif //__SBEFW_SEEPROM__
diff --git a/src/sbefw/core/sbeSecureMemRegionManager.H b/src/sbefw/core/sbeSecureMemRegionManager.H
new file mode 100644
index 00000000..1d5fc4bd
--- /dev/null
+++ b/src/sbefw/core/sbeSecureMemRegionManager.H
@@ -0,0 +1,148 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeSecureMemRegionManager.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#pragma once
+
+#include <stdint.h>
+#include <stddef.h>
+#include "sbe_sp_intf.H"
+
+enum class memRegionMode:uint8_t
+{
+ READ = 0x01,
+ WRITE = 0x02,
+};
+
+// Structure to define a mem region
+typedef struct
+{
+ uint64_t startAddress;
+ uint32_t size;
+ uint32_t mode;
+} secureMemRegion_t;
+
+// OCC SRAM Command buffer
+constexpr uint64_t OCC_CMD_ADDR = 0xFFFBE000ull;
+constexpr uint32_t OCC_CMD_SIZE = 0xFFFBEFFF - 0xFFFBE000;
+// OCC SRAM Response buffer
+constexpr uint64_t OCC_RESP_ADDR = 0xFFFBF000ull;
+constexpr uint32_t OCC_RESP_SIZE = 0xFFFBFFFF- 0xFFFBF000;
+
+class SBESecureMemRegionManager
+{
+ protected:
+ secureMemRegion_t *iv_memRegions;
+ const size_t iv_maxRegions;
+ size_t iv_regionsOpenCnt;
+
+ /*
+ * @brief getPartialRegionSize - get the overlapping region
+ * if it exists.
+ * Also if the overlap is from the beginning,
+ * first region is returned
+ *
+ *
+ * @param[in] i_region region to check for overlap
+ *
+ * @return overlapping region
+ */
+ secureMemRegion_t getPartialRegionSize(const secureMemRegion_t i_region);
+
+ public:
+ SBESecureMemRegionManager(secureMemRegion_t *i_regions,
+ size_t i_maxRegions):
+ iv_memRegions(i_regions),
+ iv_maxRegions(i_maxRegions)
+ {
+ }
+
+ // Disable copy constructors
+ SBESecureMemRegionManager(const SBESecureMemRegionManager&) = delete;
+ SBESecureMemRegionManager& operator=(const SBESecureMemRegionManager&) = delete;
+
+ /*
+ * @brief add - Open a new memory region
+ *
+ * @param[in] i_startAddr Start address of the memory region
+ * @param[in] i_size Size of the memory region
+ * @param[in] i_mode Bit mapped access mode of the memory region
+ *
+ * @return SBE secondary RC
+ */
+ sbeSecondaryResponse add(const uint64_t i_startAddr,
+ const uint32_t i_size,
+ const uint8_t i_mode);
+ /*
+ * @brief remove - Close a memory region
+ *
+ * @param[in] i_startAddr Start address of the memory region
+ *
+ * @return SBE secondary RC
+ */
+ sbeSecondaryResponse remove(const uint64_t i_startAddr);
+ /*
+ * @brief isAccessAllowed - Check if the access is allowed
+ *
+ * @param[in] i_region region to check the access for
+ *
+ * @return SBE secondary RC
+ */
+ sbeSecondaryResponse isAccessAllowed(secureMemRegion_t i_region);
+
+ /*
+ * @brief closeAllRegions - close all non-secure regions
+ */
+ void closeAllRegions()
+ {
+ iv_regionsOpenCnt = 0;
+ }
+};
+
+class SBEOccSramSecMemRegionManager : public SBESecureMemRegionManager
+{
+ public:
+ SBEOccSramSecMemRegionManager(secureMemRegion_t *i_regions,
+ size_t i_maxRegions):
+ SBESecureMemRegionManager(i_regions,
+ i_maxRegions)
+ {
+ add(OCC_CMD_ADDR,
+ OCC_CMD_SIZE,
+ static_cast<uint8_t>( memRegionMode::WRITE) |
+ static_cast<uint8_t>(memRegionMode::READ));
+ add(OCC_RESP_ADDR,
+ OCC_RESP_SIZE,
+ static_cast<uint8_t>(memRegionMode::READ));
+ }
+
+ // Disable copy constructors
+ SBEOccSramSecMemRegionManager(const SBEOccSramSecMemRegionManager&) = delete;
+ SBEOccSramSecMemRegionManager& operator=(const SBEOccSramSecMemRegionManager&) = delete;
+ // Disable delete functions
+ sbeSecondaryResponse remove(const uint64_t i_startAddr) = delete;
+ void closeAllRegions() = delete;
+
+};
+
+extern SBESecureMemRegionManager mainStoreSecMemRegionManager;
+extern SBEOccSramSecMemRegionManager occSramSecRegionManager;
diff --git a/src/sbefw/core/sbeSecurity.C b/src/sbefw/core/sbeSecurity.C
new file mode 100644
index 00000000..3e0090df
--- /dev/null
+++ b/src/sbefw/core/sbeSecurity.C
@@ -0,0 +1,157 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeSecurity.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "sbeSecurity.H"
+#include "sbetrace.H"
+#include "sbeglobals.H"
+
+#include "sbeSecurityGen.H"
+
+namespace SBE_SECURITY
+{
+
+// Figure out at compile time, the number of shifts required for the mask
+constexpr uint32_t get_shift_len(uint32_t mask, uint8_t shifts = 0)
+{
+ return ((mask>>shifts) & 0x01) ? (shifts) : (get_shift_len(mask, ++shifts));
+}
+
+template <typename Func>
+map_t<bool, int32_t> binary_search(
+ const uint32_t search_key,
+ range_t<int32_t> x_range,
+ Func get_element)
+{
+ map_t<bool, int32_t> ret = {false, 0}; // found=false
+
+ while((x_range.start <= x_range.end) &&
+ (ret.key == false))
+ {
+ int32_t midpoint = (x_range.start + x_range.end) / 2;
+ SBE_DEBUG("binary_search : midpoint[0x%08x]",
+ midpoint);
+ uint32_t ele = get_element(midpoint);
+ SBE_DEBUG("binary_search : search_key[0x%08x] ele[0x%08x]",
+ search_key,
+ ele);
+ if(search_key == ele)
+ {
+ ret.key = true;
+ ret.value = midpoint;
+ }
+ else if(search_key < ele)
+ {
+ x_range.end = midpoint - 1;
+ }
+ else
+ {
+ x_range.start = midpoint + 1;
+ }
+ SBE_DEBUG("binary_search : x_range.start[0x%08x] x_range.end[0x%08x]",
+ x_range.start,
+ x_range.end);
+ }
+ SBE_DEBUG("binary_search : ret[%d]",ret.key);
+ return ret;
+}
+
+template <typename M1_T, typename M1_U,
+ typename M2_T, typename M2_U,
+ typename T3>
+bool _is_present(const table< map_t< range_t<M1_T>, M1_U > > &table1,
+ const table< map_t<M2_T, M2_U> > &table2,
+ const table< T3 > &table3,
+ const uint32_t i_addr)
+{
+#define SBE_FUNC "SBE_SECURITY::_is_present"
+ SBE_ENTER(SBE_FUNC);
+ for(size_t i = 0; i < table1.size; i++)
+ {
+ uint32_t search_key = (i_addr & table1.mask) >> get_shift_len(table1.mask);
+ if((table1.table[i].key.start <= search_key) &&
+ (table1.table[i].key.end >= search_key))
+ {
+ SBE_DEBUG(SBE_FUNC" table1:found key[0x%x] table index[%d]",
+ search_key, i);
+ // Found the range where key might belong to
+ search_key = (i_addr & table2.mask) >> get_shift_len(table2.mask);
+ range_t<int32_t> search_range = {};
+ search_range.start = i ? table1.table[i-1].value : 0;
+ search_range.end = table1.table[i].value - 1;
+ map_t<bool, int32_t> search_result =
+ binary_search(
+ search_key,
+ search_range,
+ [&table2](int32_t midpoint) -> uint32_t {
+ return table2.table[midpoint].key;
+ });
+ if(search_result.key == true)
+ {
+ SBE_DEBUG(SBE_FUNC" table2:found key[0x%x] table index[%d]",
+ search_key,
+ search_result.value);
+ // Found the key
+ search_range.start = (search_result.value ?
+ table2.table[search_result.value-1].value : 0);
+ search_range.end =
+ table2.table[search_result.value].value - 1;
+ search_key = (i_addr & table3.mask) >>
+ get_shift_len(table3.mask);
+ search_result = binary_search(
+ search_key,
+ search_range,
+ [&table3](int32_t midpoint) -> uint32_t {
+ return table3.table[midpoint];
+ });
+ if(search_result.key == true)
+ {
+ SBE_DEBUG(SBE_FUNC" table3:found key[0x%x] table index[%d]",
+ search_key,
+ search_result.value);
+ // Found the number
+ return true;
+ }
+ }
+ }
+ }
+ SBE_EXIT(SBE_FUNC);
+ return false;
+#undef SBE_FUNC
+}
+
+bool isAllowed(const uint32_t i_addr, accessType type)
+{
+ bool ret = true;
+ if(SBE_GLOBAL->sbeFWSecurityEnabled)
+ {
+ if(type == WRITE)
+ ret = WHITELIST::isPresent(i_addr);
+ else if(type == READ)
+ ret = !BLACKLIST::isPresent(i_addr);
+ SBE_INFO("SBE_SECURITY access[%d] allowed[%d] addr[0x%08x]",
+ type, ret, i_addr);
+ }
+ return ret;
+}
+
+} // namespace SBE_SECURITY
diff --git a/src/sbefw/core/sbeSecurity.H b/src/sbefw/core/sbeSecurity.H
new file mode 100644
index 00000000..3d7ad838
--- /dev/null
+++ b/src/sbefw/core/sbeSecurity.H
@@ -0,0 +1,91 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeSecurity.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __SBE_SECURITY_H
+#define __SBE_SECURITY_H
+
+#include <stdint.h>
+
+namespace SBE_SECURITY
+{
+ typedef enum
+ {
+ READ = 0,
+ WRITE
+ } accessType;
+
+ // type to define a range
+ template <typename T>
+ struct range_t
+ {
+ T start;
+ T end;
+ };
+
+ // key-value map used for the tables
+ template <typename T, typename U>
+ struct map_t
+ {
+ T key;
+ U value;
+ };
+
+ // table data structure
+ template <typename T>
+ struct table
+ {
+ uint8_t size;
+ uint32_t mask;
+ T *table;
+ };
+
+ /* @brief isAllowed - Public function used for address verification
+ * for a given type of access
+ *
+ * @param[in] i_addr - given address to verify
+ * @param[in] accessType - access type - READ/WRITE
+ *
+ * @return - boolean to denote if the access on the address
+ * is allowed or not
+ */
+ bool isAllowed(const uint32_t i_addr, accessType type);
+
+ /* @brief _is_present - Look up tables to find if the given
+ * address is present
+ * @param[in] table1 - table 1 - map with a range and running count
+ * @param[in] table2 - table 2 - map with value and running count
+ * @param[in] table3 - table 3 - array with values
+ * @param[in] i_addr - given address to look up
+ *
+ * @return - boolean to denote if the address in present
+ * in the list of tables
+ */
+ template <typename M1_T, typename M1_U,
+ typename M2_T, typename M2_U,
+ typename T3>
+ bool _is_present(const table< map_t< range_t<M1_T>, M1_U > > &table1,
+ const table< map_t<M2_T, M2_U> > &table2,
+ const table< T3 > &table3,
+ const uint32_t i_addr);
+}
+#endif //__SBE_SECURITY_H
diff --git a/src/sbefw/core/sbeSpMsg.C b/src/sbefw/core/sbeSpMsg.C
new file mode 100644
index 00000000..b6afb700
--- /dev/null
+++ b/src/sbefw/core/sbeSpMsg.C
@@ -0,0 +1,36 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeSpMsg.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "sbeutil.H"
+#include "sbetrace.H"
+#include "sbeSpMsg.H"
+#include "sbeglobals.H"
+
+void sbeRespGenHdr_t::init(void)
+{
+ magicCode = 0xC0DE;
+ cmdClass = SBE_GLOBAL->sbeFifoCmdHdr.cmdClass;
+ command = SBE_GLOBAL->sbeFifoCmdHdr.command;
+ primaryStatus = SBE_PRI_OPERATION_SUCCESSFUL;
+ secondaryStatus = SBE_SEC_OPERATION_SUCCESSFUL;
+}
diff --git a/src/sbefw/core/sbeSpMsg.H b/src/sbefw/core/sbeSpMsg.H
new file mode 100644
index 00000000..86f7b9e6
--- /dev/null
+++ b/src/sbefw/core/sbeSpMsg.H
@@ -0,0 +1,672 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeSpMsg.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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:12;
+ uint32_t clientId:4;
+ uint32_t cmdClass:8;
+ uint32_t command:8;
+}sbeFifoCmdReqBuf_t;
+
+/**
+ * @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 SBE_GLOBAL->sbeFifoCmdHdr does not have proper
+ * values at time of object creation.
+ *
+ */
+ void init();
+}sbeRespGenHdr_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 seqId:16;
+ uint32_t cmdClass:8;
+ uint32_t cmd:8;
+ uint32_t fapiRc;
+
+ /**
+ * @brief set failed command information
+ *
+ * @param[in] i_seqId sequence Id of command
+ * @param[in] i_cmdClass command class
+ * @param[in] i_cmd command
+ *
+ * @return
+ */
+ void inline setCmdInfo(const uint16_t i_seqId,
+ const uint8_t i_cmdClass,
+ const uint8_t i_cmd)
+ {
+ seqId = i_seqId;
+ cmdClass = i_cmdClass;
+ cmd = i_cmd;
+ }
+
+ /**
+ * @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;
+ seqId = 0;
+ cmdClass = SBE_CMD_CLASS_UNKNOWN;
+ cmd = SBE_CMD_UNKNOWN;
+ lenInWords = ( sizeof(uint32_t ) // For magicBytes + lenInWords
+ + sizeof(uint32_t) // For SeqId + CmdClass + Cmd
+ + 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 Determines if inject Mode is set
+ *
+ * @return Returns True if inject mode is set
+ * False if inject mode is not set
+ */
+ uint32_t isPbaInjectModeSet() const
+ {
+ return ((flags & SBE_MEM_ACCESS_FLAGS_INJECT_ON) ? 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
+ {
+ // Expected length in bytes is 1, 2, 4, or multiples of 8,
+ // won't work for any other values
+ uint64_t l_len = (len < 8) ? (1) : (len / 8);
+ if(flags & SBE_MEM_ACCESS_FLAGS_TARGET_PBA)
+ {
+ l_len = (l_len / 16);
+ }
+ return l_len;
+ }
+
+ /**
+ * @brief Determines if it is Host Pass-through Command
+ *
+ * @return Returns True if Host Pass-through mode is set
+ * False if Host Pass-through mode is not set
+ */
+ uint32_t isPbaHostPassThroughModeSet() const
+ {
+ return ((flags & SBE_MEM_ACCESS_FLAGS_HOST_PASS_THROUGH) ? true : false);
+ }
+
+}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;
+ char buildTag[20];
+ 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;
+
+/**
+ * @brief structure for Stop Clocks Chipop (0xA901) contents.
+ *
+ */
+typedef struct
+{
+ uint32_t targetType:16;
+ uint32_t reserved:8;
+ uint32_t chipletId:8;
+}sbeStopClocksReqMsgHdr_t;
+
+/**
+ * @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]", (uint32_t)threadOps, (uint32_t)mode, (uint32_t)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_LAST+1;
+
+ 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 maximum double words for putring RS4 payload for chipop operation
+ */
+static const uint32_t SBE_PUT_RING_RS4_MAX_DOUBLE_WORDS =
+ SBE_PUT_RING_RS4_MAX_PAYLOAD_BYTES/sizeof(uint64_t);
+
+/**
+ * @brief Put Ring message header
+ */
+typedef struct
+{
+ uint32_t reserved:16;
+ uint32_t ringMode:16;
+}sbePutRingMsgHdr_t;
+
+/**
+ * @brief Put Ring message
+ * @note This structure should have uint64_t as type as underlying
+ * platrform cast it to uint64 pointer. If we declare this as
+ * uint32, we can get allignment errors.
+ */
+typedef struct
+{
+ uint64_t rs4Payload[SBE_PUT_RING_RS4_MAX_DOUBLE_WORDS];
+}sbePutRingMsg_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_LAST >= 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/core/sbeTimerSvc.C b/src/sbefw/core/sbeTimerSvc.C
new file mode 100644
index 00000000..eea43b17
--- /dev/null
+++ b/src/sbefw/core/sbeTimerSvc.C
@@ -0,0 +1,102 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeTimerSvc.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: src/sbefw/sbeTimerSvc.C
+ *
+ * @brief This file contains the SBE timer service
+ *
+ */
+
+#include "sbetrace.H"
+#include "sbeTimerSvc.H"
+#include "sbe_sp_intf.H"
+#include "pk.h"
+
+uint32_t timerService::startTimer(uint32_t i_time, PkTimerCallback i_callBack )
+{
+ #define SBE_FUNC "timerService::startTimer "
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ do
+ {
+ int l_pkRc = 0;
+ if( !init )
+ {
+ l_pkRc = pk_timer_create(&fixedTimer, i_callBack, NULL);
+ if(l_pkRc)
+ {
+ SBE_ERROR(SBE_FUNC" Pk Timer Create failed, RC=[%d]", l_pkRc);
+ l_rc = SBE_SEC_OS_FAILURE;
+ break;
+ }
+ init = true;
+ }
+ if( isActive() )
+ {
+ SBE_ERROR(SBE_FUNC" Timer already started");
+ l_rc = SBE_SEC_TIMER_ALREADY_STARTED;
+ break;
+ }
+ // Schedule the timer
+ l_pkRc = pk_timer_schedule(&fixedTimer,
+ PK_MILLISECONDS((uint32_t)i_time));
+ if(l_pkRc)
+ {
+ SBE_ERROR(SBE_FUNC" Pk Timer Schedule failed, RC=[%d]", l_pkRc);
+ l_rc = SBE_SEC_OS_FAILURE;
+ break;
+ }
+ } while(0);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+uint32_t timerService::stopTimer( )
+{
+ #define SBE_FUNC "timerService::stopTimer "
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ PkMachineContext ctx;
+ do
+ {
+ // The critical section enter/exit set is done to ensure
+ // pk_timer_cancel operations are non-interrupible.
+ pk_critical_section_enter(&ctx);
+ if( !isActive() )
+ {
+ SBE_INFO(SBE_FUNC" Timer is not running");
+ break;
+ }
+ // Cancel the timer
+ int l_pkRc = pk_timer_cancel(&fixedTimer );
+ if(l_pkRc)
+ {
+ SBE_ERROR(SBE_FUNC" Pk Timer cancel failed, RC=[%d]", l_pkRc);
+ l_rc = SBE_SEC_OS_FAILURE;
+ break;
+ }
+ } while(0);
+ pk_critical_section_exit(&ctx);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
diff --git a/src/sbefw/core/sbeTimerSvc.H b/src/sbefw/core/sbeTimerSvc.H
new file mode 100644
index 00000000..39ac046d
--- /dev/null
+++ b/src/sbefw/core/sbeTimerSvc.H
@@ -0,0 +1,68 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeTimerSvc.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: src/sbefw/sbeTimerSvc.H
+ *
+ * @brief This file contains the SBE Timer Service
+ *
+ */
+
+#ifndef __SBEFW_TIMER_SVC_H
+#define __SBEFW_TIMER_SVC_H
+#include <stdint.h>
+#include "pk_api.h"
+
+// structure for timer service
+struct timerService
+{
+ bool init; /* Timer initialised */
+ PkTimer fixedTimer; /* pk timer */
+
+ /**
+ * @brief start timer
+ *
+ * @param[in] i_time time in ms
+ * @param[in] i_callBack callback function on timer expiry
+ *
+ * @return error code as per sbe secondary errors
+ */
+ uint32_t startTimer(uint32_t i_time, PkTimerCallback i_callBack );
+
+ /**
+ * @brief stop timer
+ *
+ * @return error code as per sbe secondary errors
+ */
+ uint32_t stopTimer();
+
+ /**
+ * @brief Returns timer status
+ */
+ inline bool isActive()
+ {
+ return ( init && pk_deque_is_queued( &(fixedTimer.deque) ));
+ }
+};
+
+#endif //__SBEFW_TIMER_SVC_H
diff --git a/src/sbefw/core/sbeXipUtils.H b/src/sbefw/core/sbeXipUtils.H
new file mode 100644
index 00000000..29df84f2
--- /dev/null
+++ b/src/sbefw/core/sbeXipUtils.H
@@ -0,0 +1,63 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeXipUtils.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#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/core/sbe_host_intf.H b/src/sbefw/core/sbe_host_intf.H
new file mode 100644
index 00000000..f392851c
--- /dev/null
+++ b/src/sbefw/core/sbe_host_intf.H
@@ -0,0 +1,135 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbe_host_intf.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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 <stdint.h>
+
+/**
+ * $Version: Conforms to HOST-SBE Interface Spec v0.9b
+ */
+
+/*
+ * 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,
+ SBE_PSU_CMD_CLASS_CNTRL_TIMER = 0xD4,
+ SBE_PSU_CMD_CLASS_SECURITY_CONTROL_MSG = 0xD6,
+ SBE_PSU_CMD_CLASS_GENERIC = 0xD7,
+ };
+
+/**
+ * @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 control timer commands
+ */
+enum sbePsuControlTimerCommands
+{
+ SBE_PSU_CMD_CONTROL_TIMER = 0x01,
+ SBE_PSU_CMD_CONTROL_TIMER_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 for SBE-Host interface for unsecure memory regions commands
+ */
+enum sbePsuUpdateMemoryRegionMessages
+{
+ SBE_PSU_MSG_UPDATE_MEM_REGION = 0x01,
+};
+
+/**
+ * @brief enums for SBE-Host interface for generic commands
+ */
+enum sbePsuGenericMessages
+{
+ SBE_PSU_GENERIC_MSG_READ_SBE_MEM = 0x03,
+ SBE_PSU_GENERIC_MSG_SET_FFDC_ADDR = 0x04,
+ SBE_PSU_GENERIC_MSG_QUIESCE = 0x05,
+ SBE_PSU_GENERIC_MSG_SYSTEM_FABRIC_MAP = 0x06,
+ SBE_PSU_GENERIC_MSG_STASH_MPIPL_CONFIG = 0x07,
+ SBE_PSU_GENERIC_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,
+};
+
+enum sbePsuCntrlTimerFlags
+{
+ SBE_PSU_FLAGS_START_TIMER = 0x0001,
+ SBE_PSU_FLAGS_STOP_TIMER = 0x0002,
+};
+
+enum sbeUnsecureMemRegionControlFlags
+{
+ SBE_MEM_REGION_OPEN_RO = 0x0011,
+ SBE_MEM_REGION_OPEN_RW = 0x0012,
+ SBE_MEM_REGION_CLOSE = 0x0020,
+};
+
+#endif // __SBEFW_SBE_HOST_INTF_H
diff --git a/src/sbefw/core/sbe_sp_intf.H b/src/sbefw/core/sbe_sp_intf.H
new file mode 100644
index 00000000..23881746
--- /dev/null
+++ b/src/sbefw/core/sbe_sp_intf.H
@@ -0,0 +1,521 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbe_sp_intf.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file 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,
+};
+
+static const uint8_t SBE_CMD_UNKNOWN = 0x00;
+
+/**
+ * @brief enums for SBE Istep Control command class
+ *
+*/
+enum sbeIplControlCommands
+{
+ SBE_CMD_EXECUTE_ISTEP = 0x01, /* Execute istep */
+ SBE_CMD_SUSPEND_IO = 0x02, /* Suspend IO */
+};
+
+/**
+ * @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_CONTROL_FAST_ARRAY = 0x01, /* Control Fast Array */
+ SBE_CMD_CONTROL_TRACE_ARRAY = 0x02, /* 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_QUIESCE = 0x06, /* Sbe Quiesce */
+};
+
+enum sbeMpIplCommands
+{
+ SBE_CMD_MPIPL_ENTER = 0x01, /* Enter MPIPL */
+ SBE_CMD_MPIPL_CONTINUE = 0x02, /* Continue MPIPL */
+ SBE_CMD_MPIPL_STOPCLOCKS = 0x03, /* Stop Clocks */
+};
+
+/**
+ * @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_USER_ERROR = 0x03,
+ SBE_PRI_INTERNAL_ERROR = 0x04,
+ SBE_PRI_UNSECURE_ACCESS_DENIED = 0x05,
+ 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_CHIPLET_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_BLACKLISTED_REG_ACCESS = 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,
+ SBE_SEC_FIFO_PARITY_ERROR = 0x12,
+ SBE_SEC_TIMER_ALREADY_STARTED = 0x13,
+ SBE_SEC_BLACKLISTED_MEM_ACCESS = 0x14,
+ SBE_SEC_MEM_REGION_NOT_FOUND = 0x15,
+ SBE_SEC_MAXIMUM_MEM_REGION_EXCEEDED = 0x16,
+ SBE_SEC_MEM_REGION_AMEND_ATTEMPTED = 0x17,
+ SBE_SEC_INPUT_BUFFER_OVERFLOW = 0x18,
+ SBE_SEC_INVALID_PARAMS = 0x19,
+ SBE_SEC_BLACKLISTED_CHIPOP_ACCESS = 0x20,
+};
+
+/**
+ * @brief enums for SBE command timeout values
+ *
+*/
+enum sbeCmdRespTimeout
+{
+ SBE_CMD_TIMEOUT_SHORT_IN_MSEC = 100,
+ SBE_CMD_TIMEOUT_LONG_IN_MSEC = 30000,
+};
+
+/**
+ * @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,
+ SUSPEND_IO_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 = 0xA4000020,
+ GET_REGISTER_SUPPPORTED = 0xA5000001,
+ PUT_REGISTER_SUPPPORTED = 0xA5000002,
+ CONTROL_FAST_ARRAY_SUPPPORTED = 0xA6000001,
+ CONTROL_TRACE_ARRAY_SUPPPORTED = 0xA6000002,
+ CONTROL_INSTRUCTIONS_SUPPPORTED = 0xA7000001,
+ GET_SBE_FFDC_SUPPPORTED = 0xA8000001,
+ GET_SBE_CAPABILITIES_SUPPPORTED = 0xA8000002,
+ GET_SBE_FREQUENCIES_SUPPPORTED = 0xA8000004,
+ GET_SBE_STATE_SUPPPORTED = 0xA8000008,
+ SBE_QUIESCE = 0xA8000010,
+ STOP_CLOCKS_MPIPL_SUPPORTED = 0xA9000004,
+};
+
+/**
+ * * @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
+ SBE_MEM_ACCESS_FLAGS_HOST_PASS_THROUGH = 0x0100, // Host pass through mode (PBA)
+ SBE_MEM_ACCESS_FLAGS_INJECT_ON = 0x0200, // Inject mode ( PBA put )
+};
+
+/**
+ * @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_LAST = 0x37,
+ SMT4_ALL_CORES = 0xFF,
+};
+
+/**
+ * @brief EX Chiplet Id Enum
+ */
+enum sbeExChipletId
+{
+ EX_ALL_CHIPLETS = 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,
+};
+
+
+// Base Target Type offset maintined by SBE to be used across different chip-ops
+// Need to avoid any duplicate target type since it is used to convert into FAPI
+// target via file sbefapiutil.C
+
+/*
+ * @brief enums for target types used in ring access chip op and
+ * in stop clocks chip ops
+*/
+typedef enum
+{
+ TARGET_PROC_CHIP = 0x0000,
+ TARGET_EX = 0x0001,
+ TARGET_PERV = 0x0002,
+ TARGET_MCS = 0x0003,
+ TARGET_EQ = 0x0004,
+ TARGET_CORE = 0x0005,
+} sbeTargetTypes_t;
+
+/**
+ * @brief Pervasive Chiplet Id Enum
+ */
+enum sbePervChipletId
+{
+ PERV_CHIPLET = 0x01,
+};
+
+/**
+ * @brief Nest Chiplet Id Enum
+ */
+enum sbeNestChipletId
+{
+ NEST_ID_0 = 0x02,
+ NEST_ID_LAST = 0x05,
+};
+
+/**
+ * @brief XBus Chiplet Id Enum
+ */
+enum sbeXBusChipletId
+{
+ XBUS_ID = 0x06,
+};
+
+/**
+ * @brief MC Bist Chiplet Id Enum
+ */
+enum sbeMcbistChipletId
+{
+ MCBIST_ID_0 = 0x07,
+ MCBIST_ID_LAST = 0x08,
+};
+
+/**
+ * @brief OBus Chiplet Id Enum
+ */
+enum sbeObusChipletId
+{
+ OBUS_ID_0 = 0x09,
+ OBUS_ID_LAST = 0x0C,
+};
+
+/**
+ * @brief PCIe Chiplet Id Enum
+ */
+enum sbePcieChipletId
+{
+ PCIE_ID_0 = 0x0D,
+ PCIE_ID_LAST = 0x0F,
+};
+
+/**
+ * @brief Cache Chiplet Id Enum
+ */
+enum sbeCacheChipletId
+{
+ EQ_ID_0 = 0x10,
+ EQ_ID_LAST = 0x15,
+ EQ_ALL_CHIPLETS = 0xFF,
+};
+
+/*
+ * @brief maximum length for putring RS4 payload for chipop operation
+*/
+static const uint32_t SBE_PUT_RING_RS4_MAX_PAYLOAD_BYTES = 512;
+/*
+ * @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
+ SBE_RING_MODE_FASTARRAY = 0x0020, //Fast array mode
+
+ SBE_RING_MODE_APPLY_OVERRIDE = 0x0040, //override mode
+} sbeRingAccessModes_t;
+
+// Trace array chip-op operation bitmaps
+static const uint16_t SBE_TA_RESET = 0x0001;
+static const uint16_t SBE_TA_RESTART = 0x0002;
+static const uint16_t SBE_TA_STOP = 0x0004;
+static const uint16_t SBE_TA_COLLECT_DUMP = 0x0008;
+static const uint16_t SBE_TA_IGNORE_MUX_SETTING = 0x0010;
+
+/*
+ * @brief enums for fast array control mode
+ */
+typedef enum
+{
+ FASTARRAY_SETUP = 0x01,
+ FASTARRAY_SKIPCYCLES = 0x02,
+ FASTARRAY_CLEANUP = 0x03,
+} sbeFastArrayControlModes_t;
+
+/*
+ * @brief enums for SBE client ID
+ */
+typedef enum
+{
+ CLIENT_DEFAULT = 0x0,
+ CLIENT_SP = 0x1,
+ CLIENT_HOST = 0x2,
+ CLIENT_LAB = 0x3,
+ CLIENT_OCC = 0x4,
+} sbeClientId_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SBEFW_SBE_SP_INTF_H */
diff --git a/src/sbefw/core/sbecmdCntrlTimer.C b/src/sbefw/core/sbecmdCntrlTimer.C
new file mode 100644
index 00000000..e24698ae
--- /dev/null
+++ b/src/sbefw/core/sbecmdCntrlTimer.C
@@ -0,0 +1,144 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdCntrlTimer.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: src/sbefw/sbecmdCntrlTimer.C
+ *
+ * @brief This file contains the SBE Timer Commands
+ *
+ */
+
+#include "sbecmdCntrlTimer.H"
+#include "sbetrace.H"
+#include "sbe_sp_intf.H"
+#include "sbeFFDC.H"
+#include "sbeHostMsg.H"
+#include "sbeHostUtils.H"
+#include "sbeTimerSvc.H"
+#include "sbeglobals.H"
+
+#include "fapi2.H"
+using namespace fapi2;
+
+// Global instance to track PK timer
+static timerService g_hostTimerSvc;
+
+// Callback
+void sbeTimerExpiryCallback(void *)
+{
+ #define SBE_FUNC "sbeTimerExpiryCallback "
+ SBE_ENTER(SBE_FUNC);
+
+ do
+ {
+ // indicate the Host via Bit SBE_SBE2PSU_DOORBELL_SET_BIT14
+ // that Timer has expired
+ SBE_INFO(SBE_FUNC "Updating door bell bit 14");
+ uint32_t l_rc = sbeSetSbe2PsuDbBitX(SBE_SBE2PSU_DOORBELL_SET_BIT14);
+ if(l_rc)
+ {
+ SBE_ERROR(SBE_FUNC " Failed to Write "
+ "SBE_SBE2PSU_DOORBELL_SET_BIT14");
+ pk_halt();
+ }
+ }while(0);
+ SBE_EXIT(SBE_FUNC);
+ #undef SBE_FUNC
+
+}
+/////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------
+uint32_t sbeCntrlTimer( uint8_t *i_pArg )
+{
+ #define SBE_FUNC "sbeCntrlTimer "
+ SBE_ENTER(SBE_FUNC);
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t l_fapiRc = FAPI2_RC_SUCCESS;
+
+ do
+ {
+ if(SBE_GLOBAL->sbePsu2SbeCmdReqHdr.flags & SBE_PSU_FLAGS_START_TIMER)
+ {
+ uint64_t time = 0;
+ l_rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1,
+ (sizeof(time)/sizeof(uint64_t)),
+ &time, true);
+
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_ERROR(SBE_FUNC" Failed to extract SBE_HOST_PSU_MBOX_REG1");
+ break;
+ }
+
+ SBE_INFO(SBE_FUNC "Start Timer. Time: [%08X]",
+ SBE::lower32BWord(time));
+
+ l_rc = g_hostTimerSvc.startTimer( (uint32_t )time,
+ (PkTimerCallback)&sbeTimerExpiryCallback);
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INTERNAL_ERROR, l_rc);
+ SBE_ERROR(SBE_FUNC" g_hostTimerSvc.startTimer failed");
+ l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ break;
+ }
+ break;
+ }
+ // Acknowledge host
+ l_rc = sbeAcknowledgeHost();
+ if(l_rc)
+ {
+ SBE_ERROR(SBE_FUNC " Failed to Sent Ack to Host over "
+ "SBE_SBE2PSU_DOORBELL_SET_BIT1");
+ break;
+ }
+
+ if(SBE_GLOBAL->sbePsu2SbeCmdReqHdr.flags & SBE_PSU_FLAGS_STOP_TIMER)
+ {
+ SBE_INFO(SBE_FUNC "Stop Timer.");
+ l_rc = g_hostTimerSvc.stopTimer( );
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INTERNAL_ERROR, l_rc);
+ SBE_ERROR(SBE_FUNC" g_hostTimerSvc.stopTimer failed");
+ l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ break;
+ }
+ break;
+ }
+
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus( SBE_PRI_INVALID_COMMAND,
+ SBE_SEC_COMMAND_NOT_SUPPORTED);
+ SBE_ERROR(SBE_FUNC" Not a valid flag 0x%4X",
+ (uint16_t) SBE_GLOBAL->sbePsu2SbeCmdReqHdr.flags);
+ }while(0);
+
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, l_rc);
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
diff --git a/src/sbefw/core/sbecmdCntrlTimer.H b/src/sbefw/core/sbecmdCntrlTimer.H
new file mode 100644
index 00000000..8adec307
--- /dev/null
+++ b/src/sbefw/core/sbecmdCntrlTimer.H
@@ -0,0 +1,45 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdCntrlTimer.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdCntrlTimer.H
+ *
+ * @brief This file contains the SBE control timer command details
+ *
+ */
+
+#ifndef __SBEFW_SBECMD_CNTRL_TIMER_H
+#define __SBEFW_SBECMD_CNTRL_TIMER_H
+
+#include <stdint.h>
+
+/**
+ * @brief SBE Psu Control timer chipop (0xD401)
+ *
+ * @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 sbeCntrlTimer( uint8_t *i_pArg );
+
+#endif // __SBEFW_SBECMD_CNTRL_TIMER_H
diff --git a/src/sbefw/core/sbecmdcntlinst.C b/src/sbefw/core/sbecmdcntlinst.C
new file mode 100644
index 00000000..8674c97a
--- /dev/null
+++ b/src/sbefw/core/sbecmdcntlinst.C
@@ -0,0 +1,203 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdcntlinst.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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;
+
+// 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.
+#ifdef SEEPROM_IMAGE
+p9_thread_control_FP_t threadCntlhwp = &p9_thread_control;
+#endif
+
+/* @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<uint64_t> l_data64;
+ uint64_t l_state;
+ do
+ {
+ fapi2::Target<fapi2::TARGET_TYPE_CORE>
+ l_coreTgt(plat_getTargetHandleByChipletNumber
+ <fapi2::TARGET_TYPE_CORE>(l_core));
+ if(!l_coreTgt.isFunctional())
+ {
+ continue;
+ }
+
+ uint8_t l_thread = l_threadCnt;
+ do
+ {
+ // Call the Procedure
+ SBE_EXEC_HWP(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) && (IGNORE_HW_ERRORS != l_req.mode))
+ {
+ 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/core/sbecmdcntlinst.H b/src/sbefw/core/sbecmdcntlinst.H
new file mode 100644
index 00000000..f0515602
--- /dev/null
+++ b/src/sbefw/core/sbecmdcntlinst.H
@@ -0,0 +1,50 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdcntlinst.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdcntlinst.H
+ *
+ * @brief This file contains the Interfaces for Control Instructions chip-ops
+ *
+ */
+
+#ifndef __SBEFW_SBECMDCNTLINST_H
+#define __SBEFW_SBECMDCNTLINST_H
+
+#include <stdint.h>
+
+
+// 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;
+
+/**
+ * @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/core/sbecmdcntrldmt.C b/src/sbefw/core/sbecmdcntrldmt.C
new file mode 100644
index 00000000..4fac1d59
--- /dev/null
+++ b/src/sbefw/core/sbecmdcntrldmt.C
@@ -0,0 +1,367 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdcntrldmt.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: 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 "plat_hw_access.H"
+#include "p9_sbe_check_master_stop15.H"
+#ifdef DD2
+#include "p9_collect_deadman_ffdc.H"
+#endif
+#include "p9_perv_scom_addresses.H"
+#include "p9_block_wakeup_intr.H"
+#include "sbeTimerSvc.H"
+#include "sbeglobals.H"
+
+using namespace fapi2;
+
+#ifdef SEEPROM_IMAGE
+// 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;
+p9_block_wakeup_intr_FP_t p9_block_wakeup_intr_hwp =
+ &p9_block_wakeup_intr;
+#endif
+
+////////////////////////////////////////////////////////////////////
+//Static initialization of the Dmt Pk timer
+static timerService g_sbe_pk_dmt_timer;
+
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+void sbeDmtPkExpiryCallback(void *)
+{
+ #define SBE_FUNC "sbeDmtPkExpiryCallback"
+ SBE_INFO (SBE_FUNC "DMT Callback Timer has expired..Checkstop the system");
+ ReturnCode fapiRc = FAPI2_RC_SUCCESS;
+
+ (void)SbeRegAccess::theSbeRegAccess().stateTransition(
+ SBE_DUMP_FAILURE_EVENT);
+
+ // check stop the system
+ plat_target_handle_t l_hndl;
+ fapiRc = putscom_abs_wrap(&l_hndl, PERV_N3_LOCAL_FIR_OR,
+ ((uint64_t)1 << N3_FIR_CORE_CHECKSTOP_BIT));
+ if(fapiRc != FAPI2_RC_SUCCESS)
+ {
+ // Scom failed
+ SBE_ERROR (SBE_FUNC "PutScom failed: REG PERV_N3_LOCAL_FIR");
+ pk_halt();
+ }
+
+ (void)SbeRegAccess::theSbeRegAccess().updateAsyncFFDCBit(true);
+ #undef SBE_FUNC
+}
+
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+uint32_t sbeCollectDeadmanFfdc (void)
+{
+ #define SBE_FUNC "sbeCollectDeadmanFfdc"
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+
+ // trace the saved aync ffdc reason and SBE state as info for debug
+ SBE_INFO (SBE_FUNC "FFDC Reason: 0x%08X States - Curr: %d Prev: %d",
+ SBE_GLOBAL->asyncFfdcRC,
+ SbeRegAccess::theSbeRegAccess().getSbeState(),
+ SbeRegAccess::theSbeRegAccess().getSbePrevState());
+
+ fapi2::Target<fapi2::TARGET_TYPE_CORE> coreTarget (
+ plat_getTargetHandleByChipletNumber <fapi2::TARGET_TYPE_CORE> (
+ (SBE_GLOBAL->deadmanCore + CORE_CHIPLET_OFFSET) ));
+
+#ifdef DD2
+ ReturnCode fapiRc = FAPI2_RC_SUCCESS;
+ // p9_collect_deadman_ffdc collects the required ffdc into the fapi rc
+ // which will be available in the SBE Global HWP FFDC region
+ SBE_EXEC_HWP ( fapiRc,
+ p9_collect_deadman_ffdc,
+ coreTarget,
+ SBE_GLOBAL->asyncFfdcRC );
+#endif
+
+ return rc;
+ #undef SBE_FUNC
+}
+
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+uint32_t sbeStartCntlDmt()
+{
+ #define SBE_FUNC "sbeStartCntlDmt"
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t l_fapiRc = FAPI2_RC_SUCCESS;
+
+ 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, true );
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_ERROR(SBE_FUNC" Failed to extract SBE_HOST_PSU_MBOX_REG1");
+ break;
+ }
+
+ l_rc = g_sbe_pk_dmt_timer.startTimer( (uint32_t )l_timerVal,
+ (PkTimerCallback)&sbeDmtPkExpiryCallback);
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INTERNAL_ERROR, l_rc);
+ SBE_ERROR(SBE_FUNC" g_sbe_pk_dmt_timer.startTimer failed");
+ l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ }
+
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, l_rc);
+
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_ERROR(SBE_FUNC" Failed to send response to Hostboot ");
+ break;
+ }
+
+ // Set DMT State
+ (void)SbeRegAccess::theSbeRegAccess().stateTransition(
+ SBE_DMT_ENTER_EVENT);
+ // To start, assume no errors will hit when starting DMT and hence
+ // default to potential timeout in stopping DMT for FFDC
+ SBE_GLOBAL->asyncFfdcRC = RC_CHECK_MASTER_STOP15_DEADMAN_TIMEOUT;
+
+ Target<TARGET_TYPE_PROC_CHIP > l_procTgt = plat_getChipTarget();
+ // Fetch the Master EX
+ uint8_t exId = 0;
+ uint8_t fuseMode = 0;
+ FAPI_ATTR_GET(fapi2::ATTR_MASTER_EX,l_procTgt,exId);
+ FAPI_ATTR_GET(ATTR_FUSED_CORE_MODE, Target<TARGET_TYPE_SYSTEM>(), fuseMode);
+ fapi2::Target<fapi2::TARGET_TYPE_EX >
+ exTgt(plat_getTargetHandleByInstance<fapi2::TARGET_TYPE_EX>(exId));
+
+ bool hwpFailed = false;
+ // Initialise both cores with fapi2::RC_CHECK_MASTER_STOP15_PENDING
+ uint32_t rcFapi[2] = {RC_CHECK_MASTER_STOP15_PENDING};
+
+ // Call HWP p9_sbe_check_master_stop15 in a loop as long as the timer is
+ // active and HWP returns RC_CHECK_MASTER_STOP15_PENDING
+ do
+ {
+ uint8_t coreCnt = 0;
+
+ for (auto &coreTgt : exTgt.getChildren<fapi2::TARGET_TYPE_CORE>())
+ {
+ // Skip calling on core that already entered stop15
+ if (rcFapi[coreCnt] == RC_CHECK_MASTER_STOP15_PENDING)
+ {
+ SBE_GLOBAL->deadmanCore = coreTgt.get().getTargetInstance();
+ // Core0 is assumed to be the master core
+ SBE_INFO ( SBE_FUNC
+ "Executing p9_sbe_check_master_stop15_hwp for"
+ " Core[%d]", SBE_GLOBAL->deadmanCore );
+ SBE_EXEC_HWP ( l_fapiRc,
+ p9_sbe_check_master_stop15_hwp,
+ coreTgt);
+ rcFapi[coreCnt++] = l_fapiRc;
+
+ if (! ((FAPI2_RC_SUCCESS == l_fapiRc) ||
+ (RC_CHECK_MASTER_STOP15_PENDING == l_fapiRc)) )
+ {
+ hwpFailed = true;
+ // Mark the failure point ..
+ SBE_GLOBAL->asyncFfdcRC =
+ RC_CHECK_MASTER_STOP15_INVALID_STATE;
+ SBE_ERROR ( SBE_FUNC" p9_sbe_check_master_stop15 failed"
+ "on core[%d]", SBE_GLOBAL->deadmanCore );
+ break;
+ }
+
+ if (!fuseMode)
+ { // mark odd core as succeeded & exit the core loop
+ rcFapi[coreCnt] = FAPI2_RC_SUCCESS;
+ break;
+ }
+ }
+ } // Core loop for check master stop 15
+
+ // Either Core failed or Both Cores succeeded
+ if ( hwpFailed || ((FAPI2_RC_SUCCESS == rcFapi[0]) &&
+ (FAPI2_RC_SUCCESS == rcFapi[1])))
+ { // Exit timer loop
+ break;
+ }
+
+ // Wait if either or both cores are pending to enter stop 15
+ // and no error on either cores
+ pk_sleep(PK_MILLISECONDS(SBE_DMT_SLEEP_INTERVAL));
+
+ // loop back only if timer is still active
+ } while (g_sbe_pk_dmt_timer.isActive());
+
+ if (hwpFailed)
+ { // exit the do .. while (0) outermost loop
+ break;
+ }
+
+ // Both cores entered stop 15 successfully, now unblock interrupts
+ for (auto coreTgt : exTgt.getChildren<fapi2::TARGET_TYPE_CORE>())
+ {
+ SBE_GLOBAL->deadmanCore = coreTgt.get().getTargetInstance();
+ SBE_INFO(SBE_FUNC "Executing p9_block_wakeup_intr_hwp for Core[%d]",
+ SBE_GLOBAL->deadmanCore);
+ SBE_EXEC_HWP(l_fapiRc, p9_block_wakeup_intr_hwp, coreTgt,
+ p9pmblockwkup::CLEAR);
+ if (l_fapiRc)
+ {
+ // Mark the failure point .. SBE waits for DMT timer to expire
+ SBE_GLOBAL->asyncFfdcRC = RC_BLOCK_WAKEUP_INTR_CHECK_FAIL;
+ SBE_ERROR(SBE_FUNC" p9_block_wakeup_intr failed for "
+ "Core[%d]", SBE_GLOBAL->deadmanCore);
+
+ break;
+ }
+ // If Success for the First core & it's a Fuse core then
+ // continue here for the Second core then go on to press the
+ // Door Bell
+ if(!fuseMode)
+ {
+ break;
+ }
+ }
+
+ // Break out for the p9_block_wakeup_intr failure above
+ // Dont press the Door bell
+ if(l_fapiRc)
+ {
+ break;
+ }
+
+ // Entered stop15 and unblocked interrupts ..
+ // 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");
+ }
+ } 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;
+ uint32_t l_fapiRc = FAPI2_RC_SUCCESS;
+
+ do
+ {
+ SBE_INFO(SBE_FUNC "Stop Timer.");
+ l_rc = g_sbe_pk_dmt_timer.stopTimer( );
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus ( SBE_PRI_INTERNAL_ERROR,
+ l_rc );
+ SBE_ERROR(SBE_FUNC"g_sbe_pk_dmt_timer.stopTimer failed");
+ l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ break;
+ }
+
+ // Reset Async FFDC RC to default success
+ SBE_GLOBAL->asyncFfdcRC = FAPI2_RC_SUCCESS;
+ // Set Runtime State
+ (void)SbeRegAccess::theSbeRegAccess().stateTransition(
+ SBE_DMT_COMP_EVENT);
+ }while(0);
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, l_rc);
+
+ 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
+ {
+ if(SBE_GLOBAL->sbePsu2SbeCmdReqHdr.flags & SBE_PSU_FLAGS_START_DMT)
+ {
+ l_rc = sbeStartCntlDmt();
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_ERROR(SBE_FUNC " Failed sbeStartCntlDmt");
+ }
+ break;
+ }
+ // 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(SBE_GLOBAL->sbePsu2SbeCmdReqHdr.flags & SBE_PSU_FLAGS_STOP_DMT)
+ {
+ l_rc = sbeStopCntlDmt();
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_ERROR(SBE_FUNC " Failed sbeStopCntlDmt");
+ }
+ break;
+ }
+ 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/core/sbecmdcntrldmt.H b/src/sbefw/core/sbecmdcntrldmt.H
new file mode 100644
index 00000000..a598e037
--- /dev/null
+++ b/src/sbefw/core/sbecmdcntrldmt.H
@@ -0,0 +1,67 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdcntrldmt.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdcntrldmt.H
+ *
+ * @brief This file contains the Core State Control Messages API header
+ *
+ */
+
+#ifndef __SBEFW_SBECMDCNTRLDMT_H
+#define __SBEFW_SBECMDCNTRLDMT_H
+
+#include <stdint.h>
+
+// 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, since this is directly getting
+// inserted, we need to use bit (63-32) = 31st bit.
+static const uint64_t N3_FIR_CORE_CHECKSTOP_BIT = 31; // 63-32 = 31
+
+/**
+ * @brief Callback for Timer Expiry for DMT
+ *
+ * @return void
+ */
+void sbeDmtPkExpiryCallback(void *arg);
+
+/**
+ * @brief Called to collect FFDC for the Deadman loop timeout
+ * into the SBE global HWP FFDC region
+ * @return SBE Secondary RC
+ */
+uint32_t sbeCollectDeadmanFfdc (void);
+
+/**
+ * @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/core/sbecmdfastarray.C b/src/sbefw/core/sbecmdfastarray.C
new file mode 100644
index 00000000..78b08921
--- /dev/null
+++ b/src/sbefw/core/sbecmdfastarray.C
@@ -0,0 +1,145 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdfastarray.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "sbecmdfastarray.H"
+#include "sbefifo.H"
+#include "sbe_sp_intf.H"
+#include "sbetrace.H"
+#include "sbeFifoMsgUtils.H"
+#include "sbeutil.H"
+#include "sbefapiutil.H"
+#include "fapi2.H"
+
+#include "p9_sbe_fastarray_setup.H"
+#include "p9_sbe_fastarray_cleanup.H"
+#include "p9_sbe_fastarray_abist_catchup.H"
+
+#ifdef SEEPROM_IMAGE
+// Using Function pointer to force long call
+p9_sbe_fastarray_setup_FP_t p9_sbe_fastarray_setup_hwp =
+ &p9_sbe_fastarray_setup;
+p9_sbe_fastarray_cleanup_FP_t p9_sbe_fastarray_cleanup_hwp =
+ &p9_sbe_fastarray_cleanup;
+p9_sbe_fastarray_abist_catchup_FP_t p9_sbe_fastarray_abist_catchup_hwp =
+ &p9_sbe_fastarray_abist_catchup;
+#endif
+
+using namespace fapi2;
+
+uint32_t sbeControlFastArray(uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbeControlFastArray"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+
+ sbeControlFastArrayCMD_t l_req = {};
+ sbeRespGenHdr_t respHdr;
+ respHdr.init();
+ sbeResponseFfdc_t l_ffdc;
+ ReturnCode l_fapiRc;
+ uint32_t l_len = 0;
+
+ do
+ {
+ l_len = sizeof(sbeControlFastArrayCMD_t)/sizeof(uint32_t);
+ l_rc = sbeUpFifoDeq_mult (l_len, (uint32_t *)&l_req); //EOT fetch
+
+ // If FIFO access failure
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+
+ SBE_INFO(SBE_FUNC" targetType [0x%04X] chipletId [0x%02X]",
+ static_cast<uint16_t>(l_req.targetType),
+ static_cast<uint8_t>(l_req.chipletId));
+ // Construct a Target from Chiplet ID and Target Type
+ plat_target_handle_t l_tgtHndl;
+ if(!sbeGetFapiTargetHandle(l_req.targetType, l_req.chipletId,
+ l_tgtHndl))
+ {
+ SBE_ERROR(SBE_FUNC "Invalid target - Type [0x%04x] Chiplet [0x%02X]",
+ static_cast<uint16_t>(l_req.targetType),
+ static_cast<uint8_t>(l_req.chipletId));
+ respHdr.setStatus(SBE_PRI_INVALID_DATA,
+ SBE_SEC_INVALID_TARGET_TYPE_PASSED);
+ break;
+ }
+
+ // Relevant only when mode is set up
+ uint64_t l_clock_regions = 0;
+ // Relevant only when mode is skip cycles
+ uint32_t l_clock_cycles = 0;
+ switch(l_req.mode)
+ {
+ case FASTARRAY_SETUP:
+ l_clock_regions = (MASK_ZERO_H32B_UINT64(l_req.hData) << 32)|
+ l_req.lData;
+ SBE_INFO(SBE_FUNC" setup:clockregion [0x%08X%08X]",
+ static_cast<uint32_t>(SBE::higher32BWord(l_clock_regions)),
+ static_cast<uint32_t>(SBE::lower32BWord(l_clock_regions)));
+ SBE_EXEC_HWP(l_fapiRc,
+ p9_sbe_fastarray_setup_hwp,
+ l_tgtHndl,
+ l_clock_regions);
+ break;
+ case FASTARRAY_SKIPCYCLES:
+ l_clock_cycles = l_req.lData;
+ SBE_INFO(SBE_FUNC" abist catchup:skipcycles [0x%08X]",
+ static_cast<uint32_t>(l_clock_cycles));
+ SBE_EXEC_HWP(l_fapiRc,
+ p9_sbe_fastarray_abist_catchup_hwp,
+ l_tgtHndl,
+ l_clock_cycles);
+ break;
+ case FASTARRAY_CLEANUP:
+ SBE_INFO(SBE_FUNC" cleanup");
+ SBE_EXEC_HWP(l_fapiRc,
+ p9_sbe_fastarray_cleanup_hwp,
+ l_tgtHndl);
+ break;
+ }
+ if(l_fapiRc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC" HWP failure:mode [0x%02X]",
+ static_cast<uint8_t>(l_req.mode));
+ SBE_ERROR(SBE_FUNC" targetType [0x%04X] "
+ "chipletId [0x%02X] data[0-31] [0x%08X] "
+ "data[0-31] [0x%08X]",
+ static_cast<uint16_t>(l_req.targetType),
+ static_cast<uint8_t>(l_req.chipletId),
+ static_cast<uint32_t>(l_req.hData),
+ static_cast<uint32_t>(l_req.lData));
+ 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_rc = sbeDsSendRespHdr( respHdr, &l_ffdc);
+ }
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
diff --git a/src/sbefw/core/sbecmdfastarray.H b/src/sbefw/core/sbecmdfastarray.H
new file mode 100644
index 00000000..950420b3
--- /dev/null
+++ b/src/sbefw/core/sbecmdfastarray.H
@@ -0,0 +1,51 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdfastarray.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __SBE_CMDFASTARRAY_H
+#define __SBE_CMDFASTARRAY_H
+
+#include <stdint.h>
+
+/*
+ * @brief Fast array command structure
+ *
+ * */
+typedef struct
+{
+ uint32_t targetType:16;
+ uint32_t chipletId:8;
+ uint32_t mode:8;
+ uint32_t hData;
+ uint32_t lData;
+} sbeControlFastArrayCMD_t;
+
+/**
+ * @brief Control Fast Array Command (0xA601)
+ *
+ * @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 sbeControlFastArray(uint8_t *i_pArg);
+
+#endif //__SBE_CMDFASTARRAY_H
diff --git a/src/sbefw/core/sbecmdgeneric.C b/src/sbefw/core/sbecmdgeneric.C
new file mode 100644
index 00000000..593e012f
--- /dev/null
+++ b/src/sbefw/core/sbecmdgeneric.C
@@ -0,0 +1,532 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdgeneric.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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"
+#include "sbeFFDC.H"
+#include "sberegaccess.H"
+#include "sbestates.H"
+#include "sbeHostMsg.H"
+#include "sbeHostUtils.H"
+#include "sbeglobals.H"
+#include "sbeXipUtils.H"
+
+#include "fapi2.H"
+//#include "p9_xip_image.h"
+
+using namespace fapi2;
+
+#ifdef __SBEFW_SEEPROM__
+// Forward declaration
+sbeCapabilityRespMsg::sbeCapabilityRespMsg()
+{
+ verMajor= SBE_FW_MAJOR_VERSION;
+ verMinor = SBE_FW_MINOR_VERSION;
+ fwCommitId = SBE_COMMIT_ID;
+ // Get hbbl section
+ P9XipHeader *hdr = getXipHdr();
+ for(uint32_t idx=0; idx<sizeof(hdr->iv_buildTag); idx++)
+ {
+ buildTag[idx] = hdr->iv_buildTag[idx];
+ }
+
+ // We can remove this for llop once all capabilities
+ // are supported
+ for(uint32_t idx = 0; idx < SBE_MAX_CAPABILITIES; idx++ )
+ {
+ capability[idx] = 0;
+ }
+ // @TODO via RTC : 160602
+ // Update Capability flags based on lastes spec.
+ capability[IPL_CAPABILITY_START_IDX] =
+ EXECUTE_ISTEP_SUPPPORTED |
+ SUSPEND_IO_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_FFDC_SUPPPORTED |
+ GET_SBE_CAPABILITIES_SUPPPORTED|
+ SBE_QUIESCE;
+
+ 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 |
+ PUT_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;
+
+ 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);
+ }while(0);
+
+ if( rc )
+ {
+ SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc);
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
+// Functions
+//----------------------------------------------------------------------------
+uint32_t sbeGetFfdc (uint8_t *i_pArg)
+{
+ #define SBE_FUNC "sbeGetFfdc "
+ SBE_ENTER(SBE_FUNC);
+ 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 to handle the RC
+ break;
+ }
+
+ SbeFFDCPackage sbeFfdcPack;
+ sbeResponseFfdc_t l_ffdc;
+
+ // If need be, force collect HWP FFDC async to the real HWP fail.
+ // Else, just send back what the SBE already has.
+ sbeFfdcPack.collectAsyncHwpFfdc ();
+
+ l_ffdc.setRc(g_FfdcData.fapiRc);
+ SBE_INFO(SBE_FUNC"FAPI RC is %x", g_FfdcData.fapiRc);
+ // If no ffdc , exit;
+ if( (l_ffdc.getRc() != FAPI2_RC_SUCCESS))
+ {
+ // making sure ffdc length is multiples of uint32_t
+ assert((g_FfdcData.ffdcLength % sizeof(uint32_t)) == 0);
+ uint32_t ffdcDataLenInWords = g_FfdcData.ffdcLength
+ / sizeof(uint32_t);
+ // Set failed command information
+ // Sequence Id is 0 by default for Fifo interface
+ // @TODO via RTC : 149074
+ // primary and secondary status should be picked
+ // from the globals.
+ l_ffdc.setCmdInfo(0, respHdr.cmdClass, respHdr.command);
+ // Add HWP specific ffdc data length
+ l_ffdc.lenInWords += ffdcDataLenInWords;
+ len = sizeof(sbeResponseFfdc_t)/sizeof(uint32_t);
+ rc = sbeDownFifoEnq_mult ( len, ( uint32_t *) &l_ffdc);
+ if (rc)
+ {
+ break;
+ }
+ //Send HWP internal Data
+ rc = sbeDownFifoEnq_mult ( ffdcDataLenInWords,
+ ( uint32_t *) &g_FfdcData.ffdcData);
+ if (rc)
+ {
+ break;
+ }
+
+ }
+ //Send the FFDC data over FIFO.
+ // @TODO via RTC : 149074
+ // primary and secondary status should be picked
+ // from the globals.
+ // Check for Primary and Secondary Status from Globals and then send
+ // internal FFDC.
+ rc = sbeFfdcPack.sendOverFIFO(respHdr,
+ SBE_FFDC_ALL_DUMP,
+ len,
+ true);
+ if (rc)
+ {
+ break;
+ }
+ rc = sbeDsSendRespHdr(respHdr);
+
+ if (rc)
+ {
+ break;
+ }
+ // If we are able to send ffdc, turn off async ffdc bit
+ (void)SbeRegAccess::theSbeRegAccess().updateAsyncFFDCBit(false);
+ SBE_GLOBAL->asyncFfdcRC = FAPI2_RC_SUCCESS;
+
+ }while(0);
+
+ if( rc )
+ {
+ SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc);
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
+//---------------------------------------------------------------------------
+uint32_t sbeSetFFDCAddr(uint8_t *i_pArg)
+{
+#define SBE_FUNC "sbeSetFFDCAddr"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t l_fapiRc = FAPI2_RC_SUCCESS;
+ sbeSetFFDCAddrReq_t l_req = {};
+
+ do
+ {
+ // Extract the request
+ // and send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1
+ rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1,
+ (sizeof(l_req)/sizeof(uint64_t)),
+ (uint64_t*)&l_req,
+ true);
+ if(SBE_SEC_OPERATION_SUCCESSFUL != rc)
+ {
+ SBE_ERROR(SBE_FUNC "Failed to extract SBE_HOST_PSU_MBOX_REG1 and "
+ "SBE_HOST_PSU_MBOX_REG2");
+ break;
+ }
+
+ l_req.getFFDCAddr(SBE_GLOBAL->hostFFDCAddr);
+ l_req.getPassThroughCmdAddr(SBE_GLOBAL->hostPassThroughCmdAddr);
+
+ SBE_INFO(SBE_FUNC" Global hostFFDCAddr size[0x%08X] Address[0x%08X%08X]",
+ static_cast<uint32_t>(SBE_GLOBAL->hostFFDCAddr.size),
+ static_cast<uint32_t>(SBE::higher32BWord(SBE_GLOBAL->hostFFDCAddr.addr)),
+ static_cast<uint32_t>(SBE::lower32BWord(SBE_GLOBAL->hostFFDCAddr.addr)));
+ SBE_INFO(SBE_FUNC" Global hostPassCmdAddr size[0x%08X] Address[0x%08X%08X]",
+ static_cast<uint32_t>(SBE_GLOBAL->hostPassThroughCmdAddr.size),
+ static_cast<uint32_t>(SBE::higher32BWord(SBE_GLOBAL->hostPassThroughCmdAddr.addr)),
+ static_cast<uint32_t>(SBE::lower32BWord(SBE_GLOBAL->hostPassThroughCmdAddr.addr)));
+
+ } while(false);
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, rc);
+
+ return rc;
+ SBE_EXIT(SBE_FUNC);
+#undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+uint32_t sbeStashKeyAddrPair( uint8_t *i_pArg )
+{
+ #define SBE_FUNC "sbeStashKeyAddrPair"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t fapiRc = FAPI2_RC_SUCCESS;
+ do
+ {
+ stashMsg_t l_stashMsg;
+ // Send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1, once both
+ // key/addr is extracted out of MBOX_REG1 and MBOX_REG2
+ rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1,
+ (sizeof(stashMsg_t)/sizeof(uint64_t)),
+ (uint64_t*)&l_stashMsg, true);
+ if(SBE_SEC_OPERATION_SUCCESSFUL != rc)
+ {
+ SBE_ERROR(SBE_FUNC" Failed to extract "
+ "SBE_HOST_PSU_MBOX_REG1/SBE_HOST_PSU_MBOX_REG2");
+ break;
+ }
+
+ SBE_INFO(SBE_FUNC "Key[0x%08X] Addr[0x%08X %08X]",
+ l_stashMsg.key, SBE::higher32BWord(l_stashMsg.addr),
+ SBE::lower32BWord(l_stashMsg.addr));
+
+ // Update the Key-Addr Pair in local Memory
+ bool update = SBE_GLOBAL->sbeKeyAddrPair.updatePair(l_stashMsg.key,
+ l_stashMsg.addr);
+ if(false == update)
+ {
+ // Update RC to indicate Host that Stash memory is full
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(
+ SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_INPUT_BUFFER_OVERFLOW);
+ break;
+ }
+ }while(0);
+
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, fapiRc, rc);
+
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+uint32_t sbeSetSystemFabricMap( uint8_t *i_pArg )
+{
+ #define SBE_FUNC "sbeSetSystemFabricMap"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t l_fapiRc = FAPI2_RC_SUCCESS;
+
+ do
+ {
+ uint64_t l_sysFabricMap = 0;
+ //send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1
+ l_rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1,
+ (sizeof(l_sysFabricMap)/sizeof(uint64_t)),
+ &l_sysFabricMap, true);
+
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_ERROR(SBE_FUNC" Failed to extract SBE_HOST_PSU_MBOX_REG1");
+ break;
+ }
+
+ SBE_INFO(SBE_FUNC "Sytem Fabric Map [0x%08X][%08X]",
+ SBE::higher32BWord(l_sysFabricMap),
+ SBE::lower32BWord(l_sysFabricMap));
+
+ PLAT_ATTR_INIT(fapi2::ATTR_SBE_SYS_CONFIG,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ l_sysFabricMap);
+ }while(0);
+
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, l_rc);
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+#endif //__SBEFW_SEEPROM__
+
+#ifndef __SBEFW_SEEPROM__
+//----------------------------------------------------------------------------
+uint32_t sbeFifoQuiesce( uint8_t *i_pArg )
+{
+ #define SBE_FUNC "sbeFifoQuiesce"
+ 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);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(rc);
+
+ // Set Quiesce State
+ (void)SbeRegAccess::theSbeRegAccess().stateTransition(
+ SBE_QUIESCE_EVENT);
+
+ rc = sbeDsSendRespHdr(respHdr);
+ if(rc != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ SBE_ERROR(SBE_FUNC "sbeDsSendRespHdr failed");
+ // Not Breaking here since we can't revert back on the set state
+ }
+ }while(0);
+
+ if( rc )
+ {
+ SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc);
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+uint32_t sbePsuQuiesce( uint8_t *i_pArg )
+{
+ #define SBE_FUNC "sbePsuQuiesce"
+ uint32_t 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.
+ rc = sbeAcknowledgeHost();
+ if (rc != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ SBE_ERROR(SBE_FUNC " Failed to Sent Ack to Host over "
+ "SBE_SBE2PSU_DOORBELL_SET_BIT1");
+ break;
+ }
+
+ // Set Quiesce State
+ (void)SbeRegAccess::theSbeRegAccess().stateTransition(
+ SBE_QUIESCE_EVENT);
+
+ rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4,
+ (uint64_t*)(&SBE_GLOBAL->sbeSbe2PsuRespHdr),
+ (sizeof(SBE_GLOBAL->sbeSbe2PsuRespHdr)/sizeof(uint64_t)),
+ true);
+ if(rc != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ SBE_ERROR(SBE_FUNC" Failed to write SBE_HOST_PSU_MBOX_REG4");
+ // Not Breaking here since we can't revert back on the set state
+ }
+ }while(0);
+
+ if( rc )
+ {
+ SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc);
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+uint32_t sbeReadMem( uint8_t *i_pArg )
+{
+ #define SBE_FUNC "sbeReadMem"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t fapiRc = FAPI2_RC_SUCCESS;
+ sbeReadMemReq_t req = {};
+
+ do
+ {
+ // Extract the request
+ // and send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1
+ rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1,
+ (sizeof(req)/sizeof(uint64_t)),
+ (uint64_t*)&req,
+ true);
+ if(SBE_SEC_OPERATION_SUCCESSFUL != rc)
+ {
+ SBE_ERROR(SBE_FUNC "Failed to extract SBE_HOST_PSU_MBOX_REG1 and "
+ "SBE_HOST_PSU_MBOX_REG2");
+ break;
+ }
+
+ if(!( req.validateReq()) )
+ {
+ SBE_ERROR(SBE_FUNC"Invalid data. offset:0x%08X size:0x%08X",
+ req.offset, req.size );
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_USER_ERROR,
+ SBE_SEC_INVALID_PARAMS);
+ break;
+ }
+
+ // Default EX Target Init. As its not LCO mode, ex does not matter.
+ fapi2::Target<fapi2::TARGET_TYPE_EX> l_ex(
+ fapi2::plat_getTargetHandleByChipletNumber<fapi2::TARGET_TYPE_EX>(
+ sbeMemAccessInterface::PBA_DEFAULT_EX_CHIPLET_ID));
+ p9_PBA_oper_flag l_myPbaFlag;
+ l_myPbaFlag.setOperationType(p9_PBA_oper_flag::INJ);
+
+ sbeMemAccessInterface pbaInterface(
+ SBE_MEM_ACCESS_PBA,
+ req.responseAddr,
+ &l_myPbaFlag,
+ SBE_MEM_ACCESS_WRITE,
+ sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES,
+ l_ex);
+ uint32_t len = req.size;
+ uint64_t *seepromAddr = req.getEffectiveAddr();
+ while( len > 0)
+ {
+ uint64_t *dataBuffer = static_cast<uint64_t*>
+ (pbaInterface.getBuffer());
+ for(size_t idx=0;
+ idx < (sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES/
+ sizeof(uint64_t));
+ idx++)
+ {
+ *dataBuffer = *seepromAddr;
+ dataBuffer++;
+ seepromAddr++;
+ }
+
+ fapi2::ReturnCode fapiRc = pbaInterface.accessGranule(
+ len == sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES);
+ if( fapiRc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ break;
+ }
+ len = len - sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES;
+ }
+ } while(false);
+
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, fapiRc, rc);
+
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+ #undef SBE_FUNC
+}
+#endif //not __SBEFW_SEEPROM__
+
diff --git a/src/sbefw/core/sbecmdgeneric.H b/src/sbefw/core/sbecmdgeneric.H
new file mode 100644
index 00000000..05bc435d
--- /dev/null
+++ b/src/sbefw/core/sbecmdgeneric.H
@@ -0,0 +1,166 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdgeneric.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdgeneric.H
+ *
+ * @brief This file contains the SBE Generic command details
+ *
+ */
+
+#ifndef __SBEFW_SBECMDGENERIC_H
+#define __SBEFW_SBECMDGENERIC_H
+
+#include <stdint.h>
+#include <p9_sbe_hb_structures.H>
+
+typedef struct sbeStashMemoryPair
+{
+ // This is coming from p9_sbe_hb_structures.H
+ keyAddrPair_t keyValuePairfromHost;
+
+ // Default Constructor to initialize addr/key to 0xFF
+ sbeStashMemoryPair()
+ {
+ for(uint8_t cnt=0; cnt<MAX_ROW_COUNT; cnt++)
+ {
+ keyValuePairfromHost.addr[cnt] = 0xFFFFFFFFFFFFFFFFULL;
+ keyValuePairfromHost.key[cnt] = 0xFF;
+ }
+ }
+
+ bool updatePair(uint8_t key, uint64_t addr)
+ {
+ bool l_return = false;
+ // Check if Key already exist, if yes update addr there
+ for(uint8_t cnt=0; cnt<MAX_ROW_COUNT; cnt++)
+ {
+ if(keyValuePairfromHost.key[cnt] == key)
+ {
+ keyValuePairfromHost.addr[cnt] = addr;
+ l_return = true;
+ break;
+ }
+ }
+ if(false == l_return) // Insert the new key into a free pair
+ {
+ for(uint8_t cnt=0; cnt<MAX_ROW_COUNT; cnt++)
+ {
+ if(keyValuePairfromHost.key[cnt] == 0xFF)
+ {
+ keyValuePairfromHost.key[cnt] = key;
+ keyValuePairfromHost.addr[cnt] = addr;
+ l_return = true;
+ break;
+ }
+ }
+ }
+ return l_return;
+ }
+
+ uint64_t fetchStashAddrAttribute()
+ {
+ return (uint64_t)((uint8_t*)(&keyValuePairfromHost));
+ }
+}sbeStashMemoryPair_t;
+
+// Message struct to receive the key/addr pair from host
+typedef struct stashMsg
+{
+ uint64_t reserve:56;
+ uint64_t key:8;
+ uint64_t addr;
+}stashMsg_t;
+
+/**
+ * @brief retrieve SBE FFDC on request from FSP. (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 sbeGetFfdc(uint8_t *i_pArg);
+
+/**
+ * @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);
+
+/**
+ * @brief SBE Fifo Quiesce (0xA806)
+ *
+ * @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 sbeFifoQuiesce(uint8_t *i_pArg);
+
+/**
+ * @brief SBE Psu Set FFDC Address(0xD704)
+ *
+ * @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 sbeSetFFDCAddr(uint8_t *i_pArg);
+
+/**
+ * @brief SBE Psu Quiesce (0xD705)
+ *
+ * @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 sbePsuQuiesce(uint8_t *i_pArg);
+
+/**
+ * @brief SBE Psu Set System Fabric Map (0xD706)
+ *
+ * @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 sbeSetSystemFabricMap(uint8_t *i_pArg);
+
+/**
+ * @brief SBE stash the key addr pair into sbe memory (0xD707)
+ *
+ * @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 sbeStashKeyAddrPair(uint8_t *i_pArg);
+
+/**
+ * @brief Read the data from SBE memory (0xD703)
+ *
+ * @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 sbeReadMem(uint8_t *i_pArg);
+#endif // __SBEFW_SBECMDGENERIC_H
diff --git a/src/sbefw/core/sbecmdiplcontrol.C b/src/sbefw/core/sbecmdiplcontrol.C
new file mode 100644
index 00000000..ae811c4c
--- /dev/null
+++ b/src/sbefw/core/sbecmdiplcontrol.C
@@ -0,0 +1,1715 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdiplcontrol.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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 "sbecmdcntrldmt.H"
+#include "sbeglobals.H"
+// TODO Workaround
+#include "plat_target_parms.H"
+
+#include "fapi2.H"
+#include "p9_misc_scom_addresses_fld.H"
+#include "p9_perv_scom_addresses_fld.H"
+#include "p9n2_quad_scom_addresses.H"
+// Pervasive HWP Header Files ( istep 2)
+#include <p9_sbe_attr_setup.H>
+#include <p9_sbe_tp_chiplet_init1.H>
+#include <p9_sbe_tp_gptr_time_initf.H>
+#include <p9_sbe_npll_initf.H>
+#include <p9_sbe_npll_setup.H>
+#include <p9_sbe_tp_switch_gears.H>
+#include <p9_sbe_clock_test2.H>
+#include <p9_sbe_tp_chiplet_reset.H>
+#include <p9_sbe_tp_repr_initf.H>
+#include <p9_sbe_tp_chiplet_init2.H>
+#include <p9_sbe_tp_arrayinit.H>
+#include <p9_sbe_tp_initf.H>
+#include <p9_sbe_tp_chiplet_init3.H>
+
+// Pervasive HWP Header Files ( istep 3)
+#include <p9_sbe_chiplet_reset.H>
+#include <p9_sbe_gptr_time_initf.H>
+#include <p9_sbe_chiplet_init.H>
+#include <p9_sbe_chiplet_pll_initf.H>
+#include <p9_sbe_chiplet_pll_setup.H>
+#include <p9_sbe_repr_initf.H>
+#include <p9_sbe_arrayinit.H>
+#include <p9_sbe_tp_enable_ridi.H>
+#include <p9_sbe_setup_boot_freq.H>
+#include <p9_sbe_nest_initf.H>
+#include <p9_sbe_nest_startclocks.H>
+#include <p9_sbe_io_initf.H>
+#include <p9_sbe_nest_enable_ridi.H>
+#include <p9_sbe_startclock_chiplets.H>
+#include <p9_sbe_scominit.H>
+#include <p9_sbe_lpc_init.H>
+#include <p9_sbe_fabricinit.H>
+#include <p9_sbe_mcs_setup.H>
+#include <p9_sbe_select_ex.H>
+// Cache HWP header file
+#include <p9_hcd_cache.H>
+#include <p9_hcd_cache_dcc_skewadjust_setup.H>
+#include <p9_hcd_cache_chiplet_l3_dcc_setup.H>
+#include <p9_hcd_cache_dpll_initf.H>
+// Core HWP header file
+#include <p9_hcd_core.H>
+
+// istep 5 hwp header files
+#include "p9_sbe_instruct_start.H"
+#include "p9_sbe_load_bootloader.H"
+
+// istep mpipl header files
+#include "p9_block_wakeup_intr.H"
+#include "p9_query_core_access_state.H"
+#include "p9_sbe_check_quiesce.H"
+#include "p9_l2_flush.H"
+#include "p9_l3_flush.H"
+#include "p9_sbe_sequence_drtm.H"
+#include "p9_thread_control.H"
+#include "sbecmdcntlinst.H"
+#include "p9_quad_power_off.H"
+#include "p9_hcd_cache_stopclocks.H"
+#include "p9_stopclocks.H"
+#include "p9_suspend_powman.H"
+#include "p9_suspend_io.H"
+
+#include "sbeXipUtils.H" // For getting hbbl offset
+#include "sbeutil.H" // For getting SBE_TO_NEST_FREQ_FACTOR
+
+#include "p9_fbc_utils.H"
+#include "sbeSecureMemRegionManager.H"
+// Forward declaration
+using namespace fapi2;
+
+bool validateIstep (uint8_t i_major, uint8_t i_minor);
+
+//typedefs
+typedef ReturnCode (*sbeIstepHwpProc_t)
+ (const Target<TARGET_TYPE_PROC_CHIP> & i_target);
+
+typedef ReturnCode (*sbeIstepHwpTpSwitchGears_t)
+ (const Target<TARGET_TYPE_PROC_CHIP> & i_target);
+
+typedef ReturnCode (*sbeIstepHwpEq_t)
+ (const Target<TARGET_TYPE_EQ> & i_target);
+
+typedef ReturnCode (*sbeIstepHwpCore_t)
+ (const Target<TARGET_TYPE_CORE> & i_target);
+
+typedef ReturnCode (*sbeIstepHwpExL2Flush_t)
+ (const Target<TARGET_TYPE_EX> & i_target,
+ const p9core::purgeData_t & i_purgeData);
+
+typedef ReturnCode (*sbeIstepHwpExL3Flush_t)
+ (const Target<TARGET_TYPE_EX> & i_target,
+ const uint32_t i_purgeType,
+ const uint32_t i_purgeAddr);
+
+typedef ReturnCode (*sbeIstepHwpCoreBlockIntr_t)
+ (const Target<TARGET_TYPE_CORE> & i_target,
+ const p9pmblockwkup::OP_TYPE i_oper);
+
+typedef ReturnCode (*sbeIstepHwpCoreScomState_t)
+ (const Target<TARGET_TYPE_CORE> & i_target,
+ bool & o_isScom,
+ bool & o_isScan);
+
+typedef ReturnCode (*sbeIstepHwpSequenceDrtm_t)
+ (const Target<TARGET_TYPE_PROC_CHIP> & i_target,
+ uint8_t & o_status);
+
+typedef ReturnCode (*sbeIstepHwpQuadPoweroff_t)
+ (const Target<TARGET_TYPE_EQ> & i_target,
+ uint64_t * o_ring_save_data);
+
+typedef ReturnCode (*sbeIstepHwpCacheInitf_t)
+ (const Target<TARGET_TYPE_EQ> & i_target,
+ const uint64_t * i_ring_save_data);
+
+typedef union
+{
+ sbeIstepHwpProc_t procHwp;
+ sbeIstepHwpEq_t eqHwp;
+ sbeIstepHwpCore_t coreHwp;
+ sbeIstepHwpExL2Flush_t exL2Hwp;
+ sbeIstepHwpExL3Flush_t exL3Hwp;
+ sbeIstepHwpCoreBlockIntr_t coreBlockIntrHwp;
+ sbeIstepHwpCoreScomState_t coreScomStateHwp;
+ sbeIstepHwpSequenceDrtm_t procSequenceDrtm;
+ sbeIstepHwpQuadPoweroff_t quadPoweroffHwp;
+ sbeIstepHwpCacheInitf_t cacheInitfHwp;
+}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 istepHwpTpSwitchGears( 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);
+ReturnCode istepNestFreq( sbeIstepHwp_t i_hwp);
+ReturnCode istepLpcInit( sbeIstepHwp_t i_hwp);
+ReturnCode istepCacheInitf( sbeIstepHwp_t i_hwp );
+
+//MPIPL Specific
+ReturnCode istepWithCoreSetBlock( sbeIstepHwp_t i_hwp );
+ReturnCode istepWithCoreState( sbeIstepHwp_t i_hwp );
+ReturnCode istepMpiplRstClrTpmBits( sbeIstepHwp_t i_hwp );
+ReturnCode istepWithProcQuiesceLQASet( sbeIstepHwp_t i_hwp );
+ReturnCode istepWithExL2Flush( sbeIstepHwp_t i_hwp );
+ReturnCode istepWithExL3Flush( sbeIstepHwp_t i_hwp );
+ReturnCode istepStartMpipl( sbeIstepHwp_t i_hwp );
+ReturnCode istepWithProcSequenceDrtm( sbeIstepHwp_t i_hwp );
+ReturnCode istepMpiplSetFunctionalState( sbeIstepHwp_t i_hwp );
+ReturnCode istepMpiplQuadPoweroff( sbeIstepHwp_t i_hwp );
+ReturnCode istepStopClockMpipl( sbeIstepHwp_t i_hwp );
+
+// Utility function to do TPM reset
+ReturnCode performTpmReset();
+
+//Utility function to update PHB functional State
+ReturnCode updatePhbFunctionalState( void );
+
+//Utility function to clear crest error latch
+ReturnCode resetCrespErrLatch( void );
+
+#ifdef SEEPROM_IMAGE
+
+//Utility function to mask special attention
+inline ReturnCode maskSpecialAttn( const Target<TARGET_TYPE_CORE>& i_target );
+// Using function pointer to force long call.
+extern p9_stopclocks_FP_t p9_stopclocks_hwp;
+extern p9_thread_control_FP_t threadCntlhwp;
+#ifndef __SBEFW_SEEPROM__
+p9_suspend_io_FP_t p9_suspend_io_hwp = &p9_suspend_io;
+p9_sbe_select_ex_FP_t p9_sbe_select_ex_hwp = &p9_sbe_select_ex;
+#endif
+#ifdef __SBEFW_SEEPROM__
+extern p9_suspend_io_FP_t p9_suspend_io_hwp;
+extern p9_sbe_select_ex_FP_t p9_sbe_select_ex_hwp;
+#endif
+
+#endif
+
+//structure for mapping SBE wrapper and HWP functions
+typedef struct
+{
+ sbeIstep_t istepWrapper;
+ sbeIstepHwp_t istepHwp;
+}istepMap_t;
+
+
+// constants
+static const uint32_t SBE_ROLE_MASK = 0x00000002;
+static const uint32_t SBE_SYSTEM_QUIESCE_TIMEOUT_LOOP = 20000;
+
+static const uint64_t SBE_LQA_DELAY_HW_US = 1000000ULL; // 1ms
+static const uint64_t SBE_LQA_DELAY_SIM_CYCLES = 0x1ULL;
+
+static const uint32_t PEC_PHB_IOVALID_BIT_SHIFT = 59;
+static const uint64_t PEC_PHB_IOVALID_BIT_MASK = 0x1ULL;
+
+// Bit-33 used to checkstop the system, Since this is directly getting inserted
+// will have to use bit (63-33) = 30th bit
+static const uint64_t N3_FIR_SYSTEM_CHECKSTOP_BIT = 30; // 63-33 = 30
+
+#ifndef __SBEFW_SEEPROM__
+sbeRole g_sbeRole = SBE_ROLE_MASTER;
+
+uint64_t G_ring_save[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+// 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;
+#endif
+
+#ifdef __SBEFW_SEEPROM__
+extern sbeRole g_sbeRole;
+extern uint64_t G_ring_save[8];
+extern fapi2::ReturnCode g_iplFailRc;
+#endif
+
+
+#ifndef __SBEFW_SEEPROM__
+static istepMap_t g_istepMpiplStartPtrTbl[MPIPL_START_MAX_SUBSTEPS] =
+ {
+#ifdef SEEPROM_IMAGE
+ // Place holder for StartMpipl, State Change, PHB State Update,
+ // Clear CRESP error latch register.
+ // Set MPIPL mode in Sratch Reg 3
+ { &istepStartMpipl, NULL },
+ // Call suspend powerman
+ { &istepWithProc, { .procHwp = &p9_suspend_powman }},
+ // Find all the child cores within proc and call hwp to know the
+ // scom state and call instruction control. Also mask spl attention
+ // from core.
+ { &istepWithCoreState, { .coreScomStateHwp = &p9_query_core_access_state }},
+ // Reset the TPM and clear the TPM deconfig bit, it's not a
+ // procedure but local SBE function
+ { &istepMpiplRstClrTpmBits, NULL },
+ // quiesce state for all units on the powerbus on its chip
+ { &istepWithProcQuiesceLQASet, { .procHwp = &p9_sbe_check_quiesce }},
+ // L2 cache flush via purge engine on each EX
+ { &istepWithExL2Flush, { .exL2Hwp = &p9_l2_flush }},
+ // L3 cache flush via purge engine on each EX
+ { &istepWithExL3Flush, { .exL3Hwp = &p9_l3_flush }},
+ // Check on Quiescing of all Chips in a System by Local SBE
+ { &istepWithProcSequenceDrtm, { .procSequenceDrtm = &p9_sbe_sequence_drtm }},
+#endif
+ };
+
+static istepMap_t g_istepMpiplContinuePtrTbl[MPIPL_CONTINUE_MAX_SUBSTEPS] =
+ {
+#ifdef SEEPROM_IMAGE
+ // Setup EC/EQ guard records
+ { &istepMpiplSetFunctionalState, NULL},
+ { &istepNoOp, NULL }, // Witherspoon only (mpipl_dump_reg)
+ { &istepNoOp, NULL }, // Witherspoon only (mpipl_query_quad_access_state)
+ { &istepNoOp, NULL }, // Witherspoon only (mpipl_hcd_core_stopclocks)
+ { &istepNoOp, NULL }, // Witherspoon only (mpipl_hcd_cache_stopclocks)
+ // p9_quad_power_off
+ { istepMpiplQuadPoweroff, { .quadPoweroffHwp = &p9_quad_power_off} },
+ // No-op
+ { &istepNoOp, NULL},
+#endif
+ };
+
+static istepMap_t g_istepStopClockPtrTbl[ISTEP_STOPCLOCK_MAX_SUBSTEPS] =
+ {
+#ifdef SEEPROM_IMAGE
+ // Stop Clock Mpipl
+ { &istepStopClockMpipl, NULL},
+#endif
+ };
+
+// File static data
+static istepMap_t g_istep2PtrTbl[ ISTEP2_MAX_SUBSTEPS ] =
+ {
+#ifdef SEEPROM_IMAGE
+ { 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 }},
+ { &istepNestFreq, { .procHwp = &p9_sbe_npll_setup }},
+ { &istepHwpTpSwitchGears, { .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 }},
+#endif
+ };
+
+static istepMap_t g_istep3PtrTbl[ ISTEP3_MAX_SUBSTEPS ] =
+ {
+#ifdef SEEPROM_IMAGE
+ { &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 }},
+ { &istepLpcInit, { .procHwp = &p9_sbe_lpc_init }},
+ { &istepWithProc, { .procHwp = &p9_sbe_fabricinit }},
+ { &istepCheckSbeMaster, NULL },
+ { &istepWithProc, { .procHwp = &p9_sbe_mcs_setup }},
+ { &istepSelectEx, NULL },
+#endif
+ };
+static istepMap_t g_istep4PtrTbl[ ISTEP4_MAX_SUBSTEPS ] =
+ {
+#ifdef SEEPROM_IMAGE
+ { &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
+ { &istepCacheInitf, { .cacheInitfHwp = &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 },
+#endif
+ };
+
+// TODO via RTC 135345
+// Add the support for istep 5 HWP
+static istepMap_t g_istep5PtrTbl[ ISTEP5_MAX_SUBSTEPS ]
+ {
+#ifdef SEEPROM_IMAGE
+ { &istepLoadBootLoader, NULL },
+ { &istepStartInstruction, { .coreHwp = &p9_sbe_instruct_start }},
+#endif
+ };
+#endif //#ifndef __SBEFW_SEEPROM__
+
+
+// Functions
+#ifndef __SBEFW_SEEPROM__
+//----------------------------------------------------------------------------
+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",
+ (uint32_t)req.major, (uint32_t)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",
+ (uint32_t)req.major,
+ (uint32_t)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;
+
+ case SBE_ISTEP_MPIPL_START:
+ rc = (g_istepMpiplStartPtrTbl[i_minor-1].istepWrapper)(
+ g_istepMpiplStartPtrTbl[i_minor-1].istepHwp);
+ break;
+
+ case SBE_ISTEP_MPIPL_CONTINUE:
+ rc = (g_istepMpiplContinuePtrTbl[i_minor-1].istepWrapper)(
+ g_istepMpiplContinuePtrTbl[i_minor-1].istepHwp);
+ break;
+
+ case SBE_ISTEP_STOPCLOCK:
+ rc = (g_istepStopClockPtrTbl[i_minor-1].istepWrapper)(
+ g_istepStopClockPtrTbl[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)
+ {
+ SBE_ERROR( SBE_FUNC" FAPI RC:0x%08X", rc);
+ (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;
+ }
+
+ 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 ) ||
+ ((SBE_ROLE_SLAVE == g_sbeRole) &&
+ (i_minor > SLAVE_LAST_MINOR_ISTEP)) )
+ {
+ valid = false;
+ }
+ break;
+
+ case SBE_ISTEP4:
+ if( (i_minor > ISTEP4_MAX_SUBSTEPS ) ||
+ (SBE_ROLE_SLAVE == g_sbeRole) )
+ {
+ valid = false;
+ }
+ break;
+
+ case SBE_ISTEP5:
+ if( (i_minor > ISTEP5_MAX_SUBSTEPS ) ||
+ (SBE_ROLE_SLAVE == g_sbeRole) )
+ {
+ valid = false;
+ }
+ break;
+
+ case SBE_ISTEP_MPIPL_START:
+ if( i_minor > MPIPL_START_MAX_SUBSTEPS )
+ {
+ valid = false;
+ }
+ break;
+
+ case SBE_ISTEP_MPIPL_CONTINUE:
+ if( i_minor > MPIPL_CONTINUE_MAX_SUBSTEPS )
+ {
+ valid = false;
+ }
+ break;
+
+ case SBE_ISTEP_STOPCLOCK:
+ if( i_minor > ISTEP_STOPCLOCK_MAX_SUBSTEPS )
+ {
+ valid = false;
+ }
+ break;
+
+ default:
+ valid = false;
+ break;
+ }
+ } while(0);
+
+ return valid;
+}
+
+//----------------------------------------------------------------------------
+
+ReturnCode performAttrSetup( )
+{
+ #define SBE_FUNC "performAttrSetup "
+ SBE_ENTER("performAttrSetup ");
+ Target<TARGET_TYPE_PROC_CHIP > proc = plat_getChipTarget();
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ do
+ {
+ SBE_EXEC_HWP(rc, p9_sbe_attr_setup, proc)
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ break;
+ }
+ // Apply the gard records
+ rc = plat_ApplyGards();
+
+ //Getting CBS_CS register value
+ fapi2::buffer<uint64_t> tempReg = 0;
+ plat_target_handle_t hndl;
+ rc = getscom_abs_wrap(&hndl,
+ PERV_CBS_CS_SCOM, tempReg.pointer());
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ break;
+ }
+ SBE_GLOBAL->sbeFWSecurityEnabled =
+ tempReg.getBit<PERV_CBS_CS_SECURE_ACCESS_BIT>();
+ }while(0);
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+
+ReturnCode istepAttrSetup( sbeIstepHwp_t i_hwp)
+{
+ return performAttrSetup();
+}
+
+//----------------------------------------------------------------------------
+
+ReturnCode istepWithProc( sbeIstepHwp_t i_hwp)
+{
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ Target<TARGET_TYPE_PROC_CHIP > proc = plat_getChipTarget();
+ assert( NULL != i_hwp.procHwp );
+ SBE_EXEC_HWP(rc, i_hwp.procHwp,proc)
+ return rc;
+}
+//----------------------------------------------------------------------------
+
+ReturnCode istepHwpTpSwitchGears( sbeIstepHwp_t i_hwp)
+{
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ Target<TARGET_TYPE_PROC_CHIP > proc = plat_getChipTarget();
+ assert( NULL != i_hwp.procHwp );
+ SBE_EXEC_HWP(rc, i_hwp.procHwp,proc)
+
+ // backup i2c mode register
+ uint32_t reg_address = PU_MODE_REGISTER_B;
+ PPE_LVD( reg_address, SBE_GLOBAL->i2cModeRegister);
+
+ return rc;
+}
+
+//----------------------------------------------------------------------------
+
+ReturnCode istepNestFreq( sbeIstepHwp_t i_hwp)
+{
+ #define SBE_FUNC "istepNestFreq "
+ Target<TARGET_TYPE_PROC_CHIP > proc = plat_getChipTarget();
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ assert( NULL != i_hwp.procHwp );
+ do
+ {
+ SBE_EXEC_HWP(rc, i_hwp.procHwp,proc)
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ break;
+ }
+ // Update PK frequency
+ SBE::updatePkFreq();
+ }while(0);
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+ReturnCode istepSelectEx( sbeIstepHwp_t i_hwp)
+{
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ Target<TARGET_TYPE_PROC_CHIP > proc = plat_getChipTarget();
+ // TODO via RTC 135345
+ // Once multicast targets are supported, we may need to pass
+ // p9selectex::ALL as input.
+ SBE_EXEC_HWP(rc, p9_sbe_select_ex_hwp, proc, p9selectex::SINGLE)
+ return rc;
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepWithEq( sbeIstepHwp_t i_hwp)
+{
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ // 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<fapi2::TARGET_TYPE_EQ > eqTgt;
+ // Put this in scope so that vector can be freed up before calling hwp.
+ {
+ Target<TARGET_TYPE_PROC_CHIP > proc = plat_getChipTarget();
+ auto eqList = proc.getChildren<fapi2::TARGET_TYPE_EQ>();
+ // 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 );
+ SBE_EXEC_HWP(rc, i_hwp.eqHwp, eqTgt )
+ return rc;
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepCacheInitf (sbeIstepHwp_t i_hwp )
+{
+ #define SBE_FUNC "istepCacheInitf"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode l_rc = FAPI2_RC_SUCCESS;
+
+ // TODO via RTC 135345
+ fapi2::Target<fapi2::TARGET_TYPE_EQ > eqTgt;
+ // Put this in scope so that vector can be freed up before calling hwp.
+ {
+ Target<TARGET_TYPE_PROC_CHIP > proc = plat_getChipTarget();
+ auto eqList = proc.getChildren<fapi2::TARGET_TYPE_EQ>();
+ // As it is workaround lets assume there will always be atleast one
+ // functional eq. No need to validate.
+ eqTgt = eqList[0];
+ }
+
+ SBE_EXEC_HWP(l_rc, i_hwp.cacheInitfHwp, eqTgt, G_ring_save)
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepWithCore( sbeIstepHwp_t i_hwp)
+{
+ #define SBE_FUNC "istepWithCore"
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+
+ // Get master Ex
+ uint8_t exId = 0;
+ uint8_t fuseMode = 0;
+ Target<TARGET_TYPE_PROC_CHIP > proc = plat_getChipTarget();
+ FAPI_ATTR_GET(fapi2::ATTR_MASTER_EX,proc,exId);
+ FAPI_ATTR_GET(ATTR_FUSED_CORE_MODE, Target<TARGET_TYPE_SYSTEM>(), fuseMode);
+ fapi2::Target<fapi2::TARGET_TYPE_EX >
+ exTgt(plat_getTargetHandleByInstance<fapi2::TARGET_TYPE_EX>(exId));
+ assert( NULL != i_hwp.coreHwp );
+
+ for (auto &coreTgt : exTgt.getChildren<fapi2::TARGET_TYPE_CORE>())
+ {
+ // Core0 is assumed to be the master core
+ SBE_EXEC_HWP(rc, i_hwp.coreHwp, coreTgt)
+ if(rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC " istepWithCore failed, RC=[0x%08X]", rc);
+ break;
+ }
+ // Only continue in case of istep4 && fuse core mode
+ if(!( (fuseMode) &&
+ (SbeRegAccess::theSbeRegAccess().getSbeMajorIstepNumber() ==
+ SBE_ISTEP4) ) )
+ {
+ break;
+ }
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+
+ReturnCode istepWithEqConditional( sbeIstepHwp_t i_hwp)
+{
+ SBE_ENTER("istepWithEqCondtional");
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM > 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<fapi2::TARGET_TYPE_SYSTEM > 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;
+}
+
+//----------------------------------------------------------------------------
+constexpr uint32_t HB_MEM_WINDOW_SIZE = 32*1024*1024; //32 MB
+ReturnCode istepLoadBootLoader( sbeIstepHwp_t i_hwp)
+{
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ // Get master Ex
+ uint8_t exId = 0;
+ Target< TARGET_TYPE_SYSTEM > sysTgt;
+ Target<TARGET_TYPE_PROC_CHIP > proc = plat_getChipTarget();
+ FAPI_ATTR_GET(fapi2::ATTR_MASTER_EX,proc,exId);
+ fapi2::Target<fapi2::TARGET_TYPE_EX >
+ exTgt(plat_getTargetHandleByInstance<fapi2::TARGET_TYPE_EX>(exId));
+ // Get hbbl section
+ P9XipHeader *hdr = getXipHdr();
+ P9XipSection *hbblSection = &(hdr->iv_section[P9_XIP_SECTION_SBE_HBBL]);
+
+ uint64_t drawer_base_address_nm0, drawer_base_address_nm1;
+ uint64_t drawer_base_address_m;
+ uint64_t drawer_base_address_mmio;
+ uint64_t l_hostboot_hrmor_offset;
+ do
+ {
+ // Update the ATTR_SBE_ADDR_KEY_STASH_ADDR before calling the bootloader,
+ // since it is going to access these data from inside.
+ uint64_t addr = SBE_GLOBAL->sbeKeyAddrPair.fetchStashAddrAttribute();
+ PLAT_ATTR_INIT(fapi2::ATTR_SBE_ADDR_KEY_STASH_ADDR, sysTgt, addr);
+ SBE_EXEC_HWP(rc, p9_sbe_load_bootloader, proc, exTgt, hbblSection->iv_size,
+ getSectionAddr(hbblSection))
+ if(rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(" p9_sbe_load_bootloader failed");
+ break;
+ }
+
+ // Open HB Dump memory Region
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
+ FAPI_ATTR_GET(fapi2::ATTR_HOSTBOOT_HRMOR_OFFSET,
+ FAPI_SYSTEM,
+ l_hostboot_hrmor_offset);
+ rc = p9_fbc_utils_get_chip_base_address_no_aliases(
+ proc,
+ ABS_FBC_GRP_ID_ONLY,
+ drawer_base_address_nm0,
+ drawer_base_address_nm1,
+ drawer_base_address_m,
+ drawer_base_address_mmio);
+ if(rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(" p9_fbc_utils_get_chip_base_address failed");
+ break;
+ }
+ drawer_base_address_nm0 += l_hostboot_hrmor_offset;
+ SBE_INFO("istep 5.1 HB Dump mem Region [0x%08X%08X]",
+ SBE::higher32BWord(drawer_base_address_nm0),
+ SBE::lower32BWord(drawer_base_address_nm0));
+ mainStoreSecMemRegionManager.add(drawer_base_address_nm0,
+ HB_MEM_WINDOW_SIZE,
+ static_cast<uint8_t>(memRegionMode::READ));
+
+ } while(0);
+ 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)
+{
+ #define SBE_FUNC "istepCheckSbeMaster "
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ do
+ {
+ rc = performTpmReset();
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" performTpmReset failed");
+ break;
+ }
+ g_sbeRole = SbeRegAccess::theSbeRegAccess().isSbeSlave() ?
+ SBE_ROLE_SLAVE : SBE_ROLE_MASTER;
+ SBE_INFO(SBE_FUNC"g_sbeRole [%x]", g_sbeRole);
+ if(SBE_ROLE_SLAVE == g_sbeRole)
+ {
+ (void)SbeRegAccess::theSbeRegAccess().stateTransition(
+ SBE_RUNTIME_EVENT);
+ }
+ }while(0);
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepNoOp( sbeIstepHwp_t i_hwp)
+{
+ SBE_INFO("istepNoOp");
+ return FAPI2_RC_SUCCESS ;
+}
+
+//----------------------------------------------------------------------------
+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;
+ (void)SbeRegAccess::theSbeRegAccess().updateAsyncFFDCBit(
+ 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
+}
+#endif // #ifndef __SBEFW_SEEPROM__
+
+// MPIPL Specific
+#ifdef __SBEFW_SEEPROM__
+//----------------------------------------------------------------------------
+ReturnCode istepWithCoreSetBlock( sbeIstepHwp_t i_hwp)
+{
+ #define SBE_FUNC "istepWithCoreSetBlock"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode l_rc = FAPI2_RC_SUCCESS;
+ Target<TARGET_TYPE_PROC_CHIP > l_procTgt = plat_getChipTarget();
+ for (auto l_coreTgt : l_procTgt.getChildren<fapi2::TARGET_TYPE_CORE>())
+ {
+ SBE_EXEC_HWP(l_rc, i_hwp.coreBlockIntrHwp, l_coreTgt, p9pmblockwkup::SET)
+ if(l_rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC " p9_block_wakeup_intr failed, RC=[0x%08X]",
+ l_rc);
+ break;
+ }
+ }
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepWithCoreState( sbeIstepHwp_t i_hwp)
+{
+ #define SBE_FUNC "istepWithCoreState"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode l_rc = FAPI2_RC_SUCCESS;
+ Target<TARGET_TYPE_PROC_CHIP > l_procTgt = plat_getChipTarget();
+ for (auto l_coreTgt : l_procTgt.getChildren<fapi2::TARGET_TYPE_CORE>())
+ {
+ bool l_isScanEnable = false;
+ bool l_isCoreScomEnabled = false;
+ SBE_EXEC_HWP(l_rc, i_hwp.coreScomStateHwp, l_coreTgt,
+ l_isCoreScomEnabled, l_isScanEnable)
+ if(l_rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC " p9_query_core_access_state failed, "
+ "RC=[0x%08X]", l_rc);
+ break;
+ }
+ if(l_isCoreScomEnabled) //true
+ {
+ uint8_t l_thread = SMT4_THREAD0;
+ fapi2::buffer<uint64_t> l_data64;
+ uint64_t l_state;
+ bool l_warnCheck = true;
+ do
+ {
+ // Call instruction control stop
+ // TODO RTC 164425 - Can we pass in 1111 i.e. all threads at the
+ // same time instead of individual threads
+ SBE_EXEC_HWP(l_rc, threadCntlhwp, l_coreTgt,
+ (SINGLE_THREAD_BIT_MASK >> l_thread),
+ PTC_CMD_STOP, l_warnCheck,l_data64, l_state)
+ if(l_rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC "p9_thread_control stop Failed for "
+ "Core Thread RC[0x%08X]", l_rc);
+ break;
+ }
+ }while(++l_thread < SMT4_THREAD_MAX);
+
+ l_rc = maskSpecialAttn(l_coreTgt);
+ if( l_rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC "maskSpecialAttn failed");
+ break;
+ }
+ }
+ }
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepMpiplRstClrTpmBits( sbeIstepHwp_t i_hwp)
+{
+ #define SBE_FUNC "istepMpiplRstClrTpmBits"
+ SBE_ENTER(SBE_FUNC);
+
+ ReturnCode l_rc = performTpmReset();
+ if( l_rc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" performTpmReset failed");
+ }
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepWithExL2Flush( sbeIstepHwp_t i_hwp)
+{
+ #define SBE_FUNC "istepWithExL2Flush"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode l_rc = FAPI2_RC_SUCCESS;
+
+ Target<TARGET_TYPE_PROC_CHIP > l_procTgt = plat_getChipTarget();
+ for (auto l_exTgt : l_procTgt.getChildren<fapi2::TARGET_TYPE_EX>())
+ {
+ p9core::purgeData_t l_purgeData;
+ // TODO RTC 164425 need to check if L2 is Scomable
+ // This will come from the HWP team.
+ SBE_EXEC_HWP(l_rc, i_hwp.exL2Hwp, l_exTgt, l_purgeData)
+ if(l_rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC " p9_l2_flush failed, RC=[0x%08X]", l_rc);
+ break;
+ }
+ }
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepWithExL3Flush( sbeIstepHwp_t i_hwp)
+{
+ #define SBE_FUNC "istepWithExL3Flush"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode l_rc = FAPI2_RC_SUCCESS;
+
+ Target<TARGET_TYPE_PROC_CHIP > l_procTgt = plat_getChipTarget();
+ for (auto l_exTgt : l_procTgt.getChildren<fapi2::TARGET_TYPE_EX>())
+ {
+ // TODO RTC 164425 need to check if L3 is Scomable
+ // This will come from the HWP team.
+ SBE_EXEC_HWP(l_rc, i_hwp.exL3Hwp, l_exTgt, L3_FULL_PURGE, 0x0)
+ if(l_rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC " p9_l3_flush failed, RC=[0x%08X]", l_rc);
+ break;
+ }
+ }
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepWithProcSequenceDrtm( sbeIstepHwp_t i_hwp)
+{
+ #define SBE_FUNC "istepWithProcSequenceDrtm"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode l_rc = FAPI2_RC_SUCCESS;
+ Target<TARGET_TYPE_PROC_CHIP > l_procTgt = plat_getChipTarget();
+
+ uint8_t l_status = 0;
+ size_t l_timeOut = SBE_SYSTEM_QUIESCE_TIMEOUT_LOOP;
+ while(l_timeOut)
+ {
+ SBE_EXEC_HWP(l_rc, i_hwp.procSequenceDrtm, l_procTgt, l_status)
+ if(l_rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC "p9_sbe_sequence_drtm failed, RC=[0x%08X]",l_rc);
+ break;
+ }
+ if(l_status)
+ {
+ SBE_INFO(SBE_FUNC "p9_sbe_sequence_drtm LQA SBE System Quiesce done");
+ break;
+ }
+ else
+ {
+ l_timeOut--;
+ // delay prior to repeating the above
+ FAPI_TRY(fapi2::delay(SBE_LQA_DELAY_HW_US, SBE_LQA_DELAY_SIM_CYCLES),
+ "Error from delay");
+ }
+ }
+ // Checkstop system if SBE system quiesce not set after the loop
+ if(!l_status || l_rc)
+ {
+ SBE_ERROR(SBE_FUNC "p9_sbe_sequence_drtm LQA SBE System Quiesce failed,"
+ "Either System Quiesce Achieved not true or procedure "
+ "failed RC=[0x%08X]",l_rc);
+ // check stop the system
+ // TODO RTC 164425 this needs to be replicated on any MPIPL Hwp failure
+ Target<TARGET_TYPE_PROC_CHIP > l_proc = plat_getChipTarget();
+ l_rc = putscom_abs_wrap(&l_proc, PERV_N3_LOCAL_FIR_OR,
+ ((uint64_t)1 << N3_FIR_SYSTEM_CHECKSTOP_BIT));
+ if(l_rc != FAPI2_RC_SUCCESS)
+ {
+ // Scom failed
+ SBE_ERROR(SBE_FUNC "PutScom failed for REG PERV_N3_LOCAL_FIR");
+ // TODO - Store the response in Async Response
+ // RTC:149074
+ }
+ }
+fapi_try_exit:
+ if(fapi2::current_err)
+ {
+ l_rc = fapi2::current_err;
+ }
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepStartMpipl( sbeIstepHwp_t i_hwp)
+{
+ #define SBE_FUNC "istepStartMpipl"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+
+ (void)SbeRegAccess::theSbeRegAccess().stateTransition(
+ SBE_ENTER_MPIPL_EVENT);
+ // Set MPIPL mode bit in Scratch Reg 3
+ (void)SbeRegAccess::theSbeRegAccess().setMpIplMode(true);
+ // Close all non-secure memory regions
+ mainStoreSecMemRegionManager.closeAllRegions();
+
+ do
+ {
+ rc = updatePhbFunctionalState();
+ if(rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC "updatePhbFunctionalState failed");
+ break;
+ }
+ rc = resetCrespErrLatch();
+ if(rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC "resetCrespErrLatch failed");
+ break;
+ }
+
+ }while(0);
+
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepMpiplQuadPoweroff( sbeIstepHwp_t i_hwp)
+{
+ #define SBE_FUNC "istepMpiplQuadPoweroff"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode l_rc = FAPI2_RC_SUCCESS;
+ if(g_sbeRole == SBE_ROLE_MASTER)
+ {
+ Target<TARGET_TYPE_PROC_CHIP > l_proc = plat_getChipTarget();
+ // Fetch the MASTER_CORE attribute
+ uint8_t l_coreId = 0;
+ FAPI_ATTR_GET(fapi2::ATTR_MASTER_CORE, l_proc, l_coreId);
+ // Construct the Master Core Target
+ fapi2::Target<fapi2::TARGET_TYPE_CORE > l_core(
+ plat_getTargetHandleByChipletNumber<fapi2::TARGET_TYPE_CORE>(
+ l_coreId + CORE_CHIPLET_OFFSET));
+ fapi2::Target<fapi2::TARGET_TYPE_EQ> l_quad =
+ l_core.getParent<fapi2::TARGET_TYPE_EQ>();
+ SBE_EXEC_HWP(l_rc, i_hwp.quadPoweroffHwp, l_quad, G_ring_save)
+ }
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepWithProcQuiesceLQASet( sbeIstepHwp_t i_hwp )
+{
+ #define SBE_FUNC "istepWithProcQuiesceLQASet"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode l_rc = FAPI2_RC_SUCCESS;
+ do
+ {
+ l_rc = istepWithProc(i_hwp);
+ if(l_rc == FAPI2_RC_SUCCESS)
+ {
+ //set the LQA Bit
+ // TODO RTC 164425 - Create another istep for Setting LQA bit after
+ // L2/L3 flush istep
+ Target<TARGET_TYPE_PROC_CHIP > l_proc = plat_getChipTarget();
+ uint64_t l_data = 0x1000000000000000ULL; //Set bit3
+ l_rc = putscom_abs_wrap(&l_proc, PU_SECURITY_SWITCH_REGISTER_SCOM, l_data);
+ if(l_rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC "PutScom failed for PU_SECURITY_SWITCH_REGISTER_SCOM");
+ break;
+ }
+ l_data = 0;
+ l_rc = getscom_abs_wrap (&l_proc, PU_SECURITY_SWITCH_REGISTER_SCOM, &l_data);
+ if(l_rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC "GetScom failed for PU_SECURITY_SWITCH_REGISTER_SCOM");
+ break;
+ }
+ SBE_INFO(SBE_FUNC "PU_SECURITY_SWITCH_REGISTER_SCOM Data [0x%08X][%08X]",
+ (uint32_t)((l_data >> 32) & 0xFFFFFFFF), (uint32_t)(l_data & 0xFFFFFFFF));
+ }
+ }while(0);
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepMpiplSetFunctionalState( sbeIstepHwp_t i_hwp )
+{
+ #define SBE_FUNC "istepMpiplSetFunctionalState"
+ SBE_ENTER(SBE_FUNC);
+ Target<TARGET_TYPE_PROC_CHIP > proc = plat_getChipTarget();
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ do
+ {
+ // Read the EQ and EC gard attributes from the chip target
+ fapi2::buffer<uint64_t> l_scratchReg1 = 0;
+ uint64_t l_scratchReg8 = 0;
+ static const uint64_t SCRATCH8_SCRATCH1REG_VALID_BIT =
+ 0x8000000000000000ULL;
+ fapi2::buffer<uint8_t> l_eqMask = 0;
+ fapi2::buffer<uint32_t> l_ecMask = 0;
+ plat_target_handle_t l_hndl;
+
+ // Set MPIPL mode bit in Scratch Reg 3
+ (void)SbeRegAccess::theSbeRegAccess().setMpIplMode(true);
+
+ rc = getscom_abs_wrap (&l_hndl,
+ PERV_SCRATCH_REGISTER_8_SCOM,
+ &l_scratchReg8);
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" Failed to read Scratch RegR8");
+ break;
+ }
+ if(l_scratchReg8 & SCRATCH8_SCRATCH1REG_VALID_BIT)
+ {
+ rc = getscom_abs_wrap (&l_hndl,
+ PERV_SCRATCH_REGISTER_1_SCOM,
+ &l_scratchReg1());
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" Failed to read Scratch Reg1");
+ break;
+ }
+
+ l_scratchReg1.extract<0, 6>(l_eqMask);
+ l_scratchReg1.extract<8, 24>(l_ecMask);
+ SBE_INFO(SBE_FUNC" Setting ATTR_EQ_GARD [0x%08X] "
+ "ATTR_EC_GARD [0x%08X]",
+ l_eqMask, l_ecMask);
+
+ PLAT_ATTR_INIT(fapi2::ATTR_EQ_GARD, proc, l_eqMask);
+ PLAT_ATTR_INIT(fapi2::ATTR_EC_GARD, proc, l_ecMask);
+
+ // Apply the gard records
+ rc = plat_ApplyGards();
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" Failed to to apply gard records");
+ break;
+ }
+
+ // TODO via RTC 135345
+ // Once multicast targets are supported, we may need to pass
+ // p9selectex::ALL as input.
+ SBE_EXEC_HWP(rc, p9_sbe_select_ex_hwp, proc, p9selectex::SINGLE)
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" Failed hwp p9_sbe_select_ex_hwp");
+ break;
+ }
+ }
+ else
+ {
+ SBE_ERROR(SBE_FUNC " Scratch Reg 1 is invalid,"
+ "not applying gard records");
+ }
+ }while(0);
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepStopClockMpipl( sbeIstepHwp_t i_hwp )
+{
+ #define SBE_FUNC "istepStopClockMpipl"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t l_fapiRc = FAPI2_RC_SUCCESS;
+ p9_stopclocks_flags l_flags; // Default Flag Values
+ Target<TARGET_TYPE_PROC_CHIP > l_procTgt = plat_getChipTarget();
+ p9hcd::P9_HCD_CLK_CTRL_CONSTANTS l_clk_regions =
+ p9hcd::CLK_REGION_ALL_BUT_PLL_REFR;
+ p9hcd::P9_HCD_EX_CTRL_CONSTANTS l_ex_select = p9hcd::BOTH_EX;
+
+ l_flags.clearAll();
+ l_flags.stop_core_clks = true;
+ l_flags.stop_cache_clks = true;
+
+ SBE_EXEC_HWP(l_fapiRc,
+ p9_stopclocks_hwp,
+ l_procTgt,
+ l_flags,
+ l_clk_regions,
+ l_ex_select);
+
+ SBE_EXIT(SBE_FUNC);
+ return l_fapiRc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+inline ReturnCode maskSpecialAttn( const Target<TARGET_TYPE_CORE>& i_target )
+{
+#define SBE_FUNC "maskSpecialAttn "
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ do
+ {
+ uint64_t maskData = 0;
+ const uint64_t ecMask = 0xffc0000000000000;
+ rc = getscom_abs_wrap (&i_target, P9N2_EX_SPA_MASK, &maskData );
+ if( rc )
+ {
+ SBE_ERROR(SBE_FUNC" Failed to read P9N2_EX_SPA_MASK");
+ break;
+ }
+ maskData = maskData | ecMask;
+ rc = putscom_abs_wrap (&i_target, P9N2_EX_SPA_MASK, maskData );
+ if( rc )
+ {
+ SBE_ERROR(SBE_FUNC" Failed to write P9N2_EX_SPA_MASK");
+ break;
+ }
+ }while(0);
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+#undef SBE_FUNC
+}
+#endif //#ifdef __SBEFW_SEEPROM__
+
+#ifndef __SBEFW_SEEPROM__
+//----------------------------------------------------------------------------
+ReturnCode performTpmReset()
+{
+ #define SBE_FUNC "performTpmReset "
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ do
+ {
+ constexpr uint64_t tpmBitMask = 0x0008000000000000ULL;
+ plat_target_handle_t tgtHndl;
+ uint64_t regData = 0;
+ rc = getscom_abs_wrap (&tgtHndl,
+ PU_PRV_MISC_PPE,
+ &regData);
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" Failed to read SBE internal reg for TPM reset");
+ break;
+ }
+
+ // To do TPM reset, first we should set bit 12 of PU_PRV_MISC_PPE
+ // and then clear it up.
+ regData = regData | tpmBitMask;
+ rc = putscom_abs_wrap(&tgtHndl, PU_PRV_MISC_PPE, regData);
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" Failed to set TPM mask");
+ break;
+ }
+
+ regData = regData & ( ~tpmBitMask);
+ rc = putscom_abs_wrap(&tgtHndl, PU_PRV_MISC_PPE, regData);
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" Failed to clear TPM mask");
+ break;
+ }
+
+ }while(0);
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode istepLpcInit( sbeIstepHwp_t i_hwp)
+{
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ Target<TARGET_TYPE_PROC_CHIP > proc = plat_getChipTarget();
+ assert( NULL != i_hwp.procHwp );
+ if( !(SbeRegAccess::theSbeRegAccess().isSbeSlave()) )
+ {
+ SBE_EXEC_HWP(rc, i_hwp.procHwp,proc);
+ }
+ return rc;
+}
+
+//----------------------------------------------------------------------------
+ReturnCode updatePhbFunctionalState( void )
+{
+ #define SBE_FUNC "updatePhbFunctionalState"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ const uint64_t pci_cplt_conf1[3] = {PEC_0_CPLT_CONF1, PEC_1_CPLT_CONF1, PEC_2_CPLT_CONF1};
+ // TODO workaround
+ extern std::vector<fapi2::plat_target_handle_t> G_vec_targets;
+ Target<TARGET_TYPE_PROC_CHIP > procTgt = plat_getChipTarget();
+ auto phbTgt_vec = procTgt.getChildren<fapi2::TARGET_TYPE_PHB>();
+
+ for (auto &phbTgt : phbTgt_vec)
+ {
+ //Get the PHB id
+ uint8_t phb_id = 0;
+ uint8_t pci_id = 0;
+ uint8_t phbPerPciCnt = 0;
+ uint64_t data = 0;
+
+ FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, phbTgt, phb_id);
+ if(phb_id == 1 || phb_id == 2)
+ {
+ pci_id = 1;
+ phbPerPciCnt = phb_id - 1; // To rotate per phb cnt within PCI from 0 to 1
+ }
+ else if(phb_id > 2)
+ {
+ pci_id = 2;
+ phbPerPciCnt = phb_id - 3; // To rotate per phb cnt within PCI from 0 to 1
+ }
+ rc = getscom_abs_wrap (&procTgt, pci_cplt_conf1[pci_id], &data);
+ if(rc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC" Failed to read Pec[%d] Chiplet Config1 register",pci_id);
+ break;
+ }
+ // Fetch bit4 from D000009 for PHB0
+ // Fetch bit4/5 from E000009 for PHB1/2
+ // Fetch bit4/5/6 from F000009 for PHB3/4/5
+ if( !((data >> (PEC_PHB_IOVALID_BIT_SHIFT - phbPerPciCnt)) & PEC_PHB_IOVALID_BIT_MASK) )
+ {
+ SBE_INFO(SBE_FUNC "PHB[%d] setting up as Non-Functional", phb_id);
+ static_cast<plat_target_handle_t&>(phbTgt.operator ()()).setFunctional(false);
+ G_vec_targets.at(PHB_TARGET_OFFSET+ phb_id) = (fapi2::plat_target_handle_t)(phbTgt.get());
+ }
+ }
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+#undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+ReturnCode resetCrespErrLatch( void )
+{
+ #define SBE_FUNC "resetCrespErrLatch"
+ SBE_ENTER(SBE_FUNC);
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ static const uint64_t BIT_63_MASK = 0x01;
+ do
+ {
+ Target<TARGET_TYPE_PROC_CHIP > procTgt = plat_getChipTarget();
+ uint64_t data;
+ rc = getscom_abs_wrap (&procTgt, PU_PB_CENT_SM0_PB_CENT_MODE,
+ &data);
+ if( rc )
+ {
+ break;
+ }
+ data = data | BIT_63_MASK;
+ rc = putscom_abs_wrap (&procTgt, PU_PB_CENT_SM0_PB_CENT_MODE,
+ data);
+ if( rc )
+ {
+ break;
+ }
+ data = data &(~BIT_63_MASK);
+ rc = putscom_abs_wrap (&procTgt, PU_PB_CENT_SM0_PB_CENT_MODE,
+ data);
+ if( rc )
+ {
+ break;
+ }
+ }while(0);
+ if( rc )
+ {
+ SBE_ERROR(SBE_FUNC" Failed to reset Cresp error latch");
+ }
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+#undef SBE_FUNC
+}
+
+///////////////////////////////////////////////////////////////////////
+// @brief sbeHandleSuspendIO Sbe suspend IO function
+//
+// @return RC from the underlying FIFO utility
+///////////////////////////////////////////////////////////////////////
+uint32_t sbeHandleSuspendIO(uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbeHandleSuspendIO "
+ SBE_ENTER(SBE_FUNC);
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ ReturnCode fapiRc = FAPI2_RC_SUCCESS;
+ uint32_t len = 0;
+ sbeRespGenHdr_t respHdr;
+ respHdr.init();
+ sbeResponseFfdc_t ffdc;
+ Target<TARGET_TYPE_PROC_CHIP > procTgt = plat_getChipTarget();
+
+ do
+ {
+ // Dequeue the EOT entry as no more data is expected.
+ rc = sbeUpFifoDeq_mult (len, NULL);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(rc);
+
+ // Update the PHB functional State before suspend io procedure
+ fapiRc = updatePhbFunctionalState();
+ if(fapiRc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC "updatePhbFunctionalState failed");
+ respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ ffdc.setRc(fapiRc);
+ break;
+ }
+
+ SBE_EXEC_HWP(fapiRc, p9_suspend_io_hwp, procTgt, false);
+ if( fapiRc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC "p9_suspend_io hwp failed");
+ respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ ffdc.setRc(fapiRc);
+ break;
+ }
+ }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
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(rc);
+ rc = sbeDsSendRespHdr( respHdr, &ffdc);
+ }while(0);
+
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+ #undef SBE_FUNC
+}
+#endif //#ifndef __SBEFW_SEEPROM__
+
diff --git a/src/sbefw/core/sbecmdiplcontrol.H b/src/sbefw/core/sbecmdiplcontrol.H
new file mode 100644
index 00000000..7b05f3f7
--- /dev/null
+++ b/src/sbefw/core/sbecmdiplcontrol.H
@@ -0,0 +1,132 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdiplcontrol.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdiplcontrol.H
+ *
+ * @brief This file contains the SBE command details
+ *
+ */
+
+#ifndef __SBEFW_SBECMDIPLCONTROL_H
+#define __SBEFW_SBECMDIPLCONTROL_H
+
+#include <stdint.h>
+#include "sbecmdgeneric.H"
+
+
+namespace fapi2
+{
+ class ReturnCode;
+}
+
+// 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;
+
+// Major MPIPL isteps which are supported
+static const uint32_t SBE_ISTEP_MPIPL_START = 96;
+static const uint32_t SBE_ISTEP_MPIPL_CONTINUE = 97;
+static const uint32_t SBE_ISTEP_STOPCLOCK = 98;
+static const uint32_t MPIPL_START_MAX_SUBSTEPS = 8;
+static const uint32_t MPIPL_CONTINUE_MAX_SUBSTEPS = 7;
+static const uint32_t ISTEP_STOPCLOCK_MAX_SUBSTEPS = 1;
+
+// constants
+static const uint32_t ISTEP2_MAX_SUBSTEPS = 17;
+static const uint32_t ISTEP3_MAX_SUBSTEPS = 22;
+static const uint32_t ISTEP4_MAX_SUBSTEPS = 34;
+static 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;
+
+extern uint64_t G_ring_save[8];
+extern const uint64_t G_ring_index[10];
+
+/**
+ * @brief Support function to execute specific istep
+ *
+ * @param[in] i_major Major Istep Number
+ * @param[in] i_minor Minor Istep Number
+ *
+ * @return FAPI2_RC_SUCCESS if success, else error code.
+ */
+fapi2::ReturnCode sbeExecuteIstep (uint8_t i_major, uint8_t i_minor);
+
+
+/**
+ * @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 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 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 execute suspend IO 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 sbeHandleSuspendIO(uint8_t *i_pArg);
+
+#endif // __SBEFW_SBECMDIPLCONTROL_H
diff --git a/src/sbefw/core/sbecmdmemaccess.C b/src/sbefw/core/sbecmdmemaccess.C
new file mode 100644
index 00000000..1160043d
--- /dev/null
+++ b/src/sbefw/core/sbecmdmemaccess.C
@@ -0,0 +1,799 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdmemaccess.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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 "sbeHostUtils.H"
+#include "sbeglobals.H"
+#include "sbeSecureMemRegionManager.H"
+
+#include "fapi2.H"
+
+#include "sbeMemAccessInterface.H"
+
+using namespace fapi2;
+
+// Buffer requirement for ADU and PBA on the stack
+constexpr uint32_t MAX_ADU_BUFFER = 5; // 40bytes
+constexpr uint32_t MAX_PBA_BUFFER = 32;
+
+// Multiplier factor with respect to the FIFO length
+constexpr uint32_t ADU_SIZE_MULTIPLIER_FOR_LEN_ALIGNMENT = 2;
+constexpr uint32_t PBA_SIZE_MULTIPLIER_FOR_LEN_ALIGNMENT = 32;
+
+/**
+ * @brief static definition of parameters passed in adu chip-ops
+ */
+constexpr uint32_t SBE_ADU_LOCK_TRIES = 3;
+
+#ifndef __SBEFW_SEEPROM__
+///////////////////////////////////////////////////////////////////////
+// @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 =
+ ((sbeMemAccessInterface::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_granuleSize
+// @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,
+ uint32_t i_granuleSize,
+ bool i_itag,
+ bool i_ecc)
+{
+ uint32_t l_respLen = i_numGranules * i_granuleSize;
+ 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_primaryStatus, Fapi RC
+//
+// @return RC from the underlying FIFO utility
+///////////////////////////////////////////////////////////////////////
+inline uint32_t flushUpstreamFifo (const uint32_t &i_primaryStatus)
+{
+ uint32_t l_len2dequeue = 0;
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ if ( i_primaryStatus != SBE_PRI_OPERATION_SUCCESSFUL)
+ {
+ 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 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_granuleSize = sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES;
+ uint64_t l_addr = 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 = 0;
+
+ do
+ {
+ // If not Host Pass through command, simply set the addr from the command
+ if(!i_hdr.isPbaHostPassThroughModeSet())
+ {
+ l_addr = i_hdr.getAddr();
+ // Check if the access to the address is allowed
+ l_respHdr.secondaryStatus = mainStoreSecMemRegionManager.isAccessAllowed(
+ {l_addr,
+ i_hdr.len,
+ (i_isFlagRead ? static_cast<uint8_t>(memRegionMode::READ):
+ static_cast<uint8_t>(memRegionMode::WRITE))});
+ if(l_respHdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ l_respHdr.primaryStatus = SBE_PRI_UNSECURE_ACCESS_DENIED;
+ break;
+ }
+ }
+ // If it is Host Pass through command, set the address using the Host pass
+ // through address already set in the global and using the addr here in the
+ // command as index to that address
+ else
+ {
+ l_addr = SBE_GLOBAL->hostPassThroughCmdAddr.addr + i_hdr.getAddr();
+ // Check if the size pass in the command is less than the size mentioned
+ // in the Host Pass Through globals
+ if((i_hdr.getAddr() + i_hdr.len) > SBE_GLOBAL->hostPassThroughCmdAddr.size)
+ {
+ // Break out, Invalid Size
+ SBE_ERROR("User size[0x%08X] exceeds the Host Pass Through Mode "
+ "size[0x%08X] Start Index[0x%08X %08X]",
+ i_hdr.len, SBE_GLOBAL->hostPassThroughCmdAddr.size,
+ SBE::higher32BWord(i_hdr.getAddr()),
+ SBE::lower32BWord(i_hdr.getAddr()));
+ l_respHdr.setStatus( SBE_PRI_INVALID_DATA,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION );
+ }
+ }
+
+ // Default EX Target Init..Not changing it for the time being
+ Target<TARGET_TYPE_EX> l_ex(
+ plat_getTargetHandleByChipletNumber<TARGET_TYPE_EX>(
+ sbeMemAccessInterface::PBA_DEFAULT_EX_CHIPLET_ID));
+
+ p9_PBA_oper_flag l_myPbaFlag;
+ // Determine the access flags
+ // Fast mode flag
+ if(i_hdr.isFastModeSet())
+ {
+ l_myPbaFlag.setFastMode(true);
+ SBE_INFO(SBE_FUNC "Fast Mode is set");
+ }
+
+ // inject mode flag
+ if(i_hdr.isPbaInjectModeSet())
+ {
+ l_myPbaFlag.setOperationType(p9_PBA_oper_flag::INJ); // Inject operation
+ SBE_INFO(SBE_FUNC "inject Mode is set");
+ }
+
+ // By default, ex_chipletId printed below won't be used unless accompanied
+ // by LCO_mode (LCO Mode for PBA-Put)
+ if(i_hdr.isPbaLcoModeSet())
+ {
+ SBE_INFO(SBE_INFO "LCO Mode is set with Ex ChipletId[%d]",
+ (i_hdr.coreChipletId)/2);
+ //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<fapi2::TARGET_TYPE_EX>
+ (i_hdr.coreChipletId);
+ l_myPbaFlag.setOperationType(p9_PBA_oper_flag::LCO); // LCO operation
+ }
+
+ l_lenCacheAligned = i_hdr.getDataLenCacheAlign();
+ SBE_DEBUG(SBE_FUNC "Data Aligned Len / Number of data granules = %d",
+ l_lenCacheAligned);
+
+ sbeMemAccessInterface l_PBAInterface(SBE_MEM_ACCESS_PBA,
+ l_addr,
+ &l_myPbaFlag,
+ (i_isFlagRead ?
+ SBE_MEM_ACCESS_READ:
+ SBE_MEM_ACCESS_WRITE),
+ l_granuleSize,
+ l_ex);
+
+ while (l_granulesCompleted < l_lenCacheAligned)
+ {
+ // Breaking out here if invalid size
+ if(l_respHdr.primaryStatus != SBE_PRI_OPERATION_SUCCESSFUL)
+ {
+ break;
+ }
+
+ // 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 = sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES
+ / sizeof(uint32_t);
+ l_rc = sbeUpFifoDeq_mult (l_len2dequeue,
+ (uint32_t *)l_PBAInterface.getBuffer(),
+ false);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ }
+
+ // Call the PBA HWP
+ l_fapiRc = l_PBAInterface.accessGranule(
+ l_granulesCompleted==(l_lenCacheAligned-1));
+ // if error
+ if(l_fapiRc != FAPI2_RC_SUCCESS)
+ {
+ // 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
+ // l_len*4 = Granule Size
+ uint32_t l_len = sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES
+ / sizeof(uint32_t);
+ l_rc = sbeDownFifoEnq_mult (l_len,
+ (uint32_t *)l_PBAInterface.getBuffer());
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ }
+
+ l_granulesCompleted++;
+ } // End..while (l_granulesCompleted < l_lenCacheAligned);
+ } while(0);
+
+ // 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_respHdr.primaryStatus);
+ 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 = l_granulesCompleted * l_granuleSize;
+
+ 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);
+ // Indicate the host in put pass through mode via Interrupt
+ if(!l_rc && i_hdr.isPbaHostPassThroughModeSet() && !i_isFlagRead)
+ {
+ l_rc = sbeSetSbe2PsuDbBitX(SBE_SBE2PSU_DOORBELL_SET_BIT4);
+ }
+ } while(false);
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+///////////////////////////////////////////////////////////////////////
+// @brief processAduRequest - Internal Method to this file,
+// To process the ADU Access request
+//
+// @param [in] i_hdr, Message Request Header
+// @param [in] i_isFlagRead, Read/Write Flag
+//
+// @return RC from the method
+///////////////////////////////////////////////////////////////////////
+#define IS_ONE_BIT_SET(x) ((x & (x-1)) == 0)
+#define GET_8_BYTE_ALIGNED_OFFSET(x) ((x & 0x07) * 8)
+uint32_t processAduRequest(const sbeMemAccessReqMsgHdr_t &i_hdr,
+ const bool i_isFlagRead)
+{
+ #define SBE_FUNC " processAduRequest "
+ 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 ADU
+ uint32_t l_sizeMultiplier = ADU_SIZE_MULTIPLIER_FOR_LEN_ALIGNMENT;
+ uint32_t l_granuleSize = sbeMemAccessInterface::ADU_GRAN_SIZE_BYTES;
+
+ // Keeps track of number of granules sent to HWP
+ uint64_t l_granulesCompleted = 0;
+ p9_ADU_oper_flag l_aduFlag;
+ // For local Use
+ bool l_isEccMode = i_hdr.isEccFlagSet();
+ bool l_isItagMode = i_hdr.isItagFlagSet();
+ uint64_t l_addr = i_hdr.getAddr();
+
+ do
+ {
+ l_aduFlag.setTransactionSize(p9_ADU_oper_flag::TSIZE_8);
+ // For len lesser than 8, only 1,2 and 4 lengths are allowed
+ if(i_hdr.len < 8)
+ {
+ if(IS_ONE_BIT_SET(i_hdr.len) == false)
+ {
+ l_respHdr.setStatus(SBE_PRI_INVALID_DATA,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ SBE_ERROR(SBE_FUNC"Invalid length[%d] - "
+ "supported values[1/2/4/multiples of 8]",
+ i_hdr.len);
+ break;
+ }
+ l_sizeMultiplier = 1;
+ l_granuleSize = i_hdr.len;
+ l_aduFlag.setTransactionSize((p9_ADU_oper_flag::Transaction_size_t)(i_hdr.len));
+ }
+ //Default Operation Type is DMA_PARTIAL
+ l_aduFlag.setOperationType(p9_ADU_oper_flag::DMA_PARTIAL);
+ l_aduFlag.setLockControl(false);
+ l_aduFlag.setOperFailCleanup(true);
+ l_aduFlag.setNumLockAttempts(SBE_ADU_LOCK_TRIES);
+
+ // Fast Mode / Ecc mode / Cache Inhibit Mode / Auto Increment
+ // required in ADU operations.
+ if(i_hdr.isFastModeSet())
+ {
+ l_aduFlag.setFastMode(true);
+ }
+ // Set DMA_PARTIAL mode by default
+ l_aduFlag.setOperationType(p9_ADU_oper_flag::DMA_PARTIAL);
+ if(i_hdr.isCacheInhibitModeFlagSet())
+ {
+ l_aduFlag.setOperationType(p9_ADU_oper_flag::CACHE_INHIBIT);
+ }
+ if(i_hdr.isItagFlagSet())
+ {
+ l_aduFlag.setItagMode(true);
+ }
+ if(i_hdr.isAutoIncrModeSet())
+ {
+ l_aduFlag.setAutoIncrement(true);
+ }
+
+ if(!i_isFlagRead) // ECC override in write mode
+ {
+ if(i_hdr.isEccOverrideFlagSet())
+ {
+ l_aduFlag.setEccItagOverrideMode(true);
+ l_aduFlag.setEccMode(true);
+ }
+ }
+ else // ECC required in read mode
+ {
+ if(i_hdr.isEccFlagSet())
+ {
+ l_aduFlag.setEccMode(true);
+ }
+ }
+
+ // Input Data length in alignment with ADU
+ // 1 for 1/2/4 Bytes else number of multiples of 8 Bytes
+ uint64_t l_lenCacheAligned = i_hdr.getDataLenCacheAlign();
+ SBE_DEBUG(SBE_FUNC "User length [%d], Data Aligned Len / "
+ "Number of data granules = %d",
+ i_hdr.len, l_lenCacheAligned);
+
+ sbeMemAccessInterface l_ADUInterface(SBE_MEM_ACCESS_ADU,
+ l_addr,
+ &l_aduFlag,
+ (i_isFlagRead ?
+ SBE_MEM_ACCESS_READ :
+ SBE_MEM_ACCESS_WRITE),
+ sbeMemAccessInterface::ADU_GRAN_SIZE_BYTES);
+ // Check if the access to the address is allowed
+ l_respHdr.secondaryStatus = mainStoreSecMemRegionManager.isAccessAllowed(
+ {l_addr,
+ i_hdr.len,
+ (i_isFlagRead ? static_cast<uint8_t>(memRegionMode::READ):
+ static_cast<uint8_t>(memRegionMode::WRITE))});
+ if(l_respHdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ l_respHdr.primaryStatus = SBE_PRI_UNSECURE_ACCESS_DENIED;
+ break;
+ }
+ // 8Byte granule for ADU access
+ uint64_t l_dataFifo[MAX_ADU_BUFFER] = {0};
+ while (l_granulesCompleted < l_lenCacheAligned)
+ {
+ // 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 8B
+ 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);
+ SBE_DEBUG("l_dataFifo#1 0x%08x%08x", SBE::higher32BWord(l_dataFifo[0]),
+ SBE::lower32BWord(l_dataFifo[0]));
+ // For lengths 1,2 and 4, data needs to be shift-aligned to
+ // 8-byte address boundary.
+ l_dataFifo[0] >>= GET_8_BYTE_ALIGNED_OFFSET(l_addr);
+ SBE_DEBUG("l_dataFifo#2 0x%08x%08x", SBE::higher32BWord(l_dataFifo[0]),
+ SBE::lower32BWord(l_dataFifo[0]));
+
+ // 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_granulesCompleted % 4);
+ if( (l_mod) && ((l_isEccMode) || (l_isItagMode)) )
+ {
+ // Default Init it for 1byte extra
+ l_bufIdx = (sbeMemAccessInterface::ADU_GRAN_SIZE_BYTES
+ * l_mod) + l_mod;
+ if((l_isEccMode) && (l_isItagMode))
+ {
+ l_bufIdx = l_bufIdx + l_mod;
+ }
+ }
+ }
+ l_fapiRc = l_ADUInterface.accessWithBuffer(
+ &(((uint8_t *)&(l_dataFifo))[l_bufIdx]),
+ sbeMemAccessInterface::ADU_GRAN_SIZE_BYTES,
+ (l_granulesCompleted == (l_lenCacheAligned-1)));
+ // if error
+ if( (l_fapiRc != FAPI2_RC_SUCCESS) )
+ {
+ // 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.
+
+ if((l_isEccMode) || (l_isItagMode))
+ {
+ //Calculate the MODULUS
+ uint8_t l_mod = (l_granulesCompleted % 4);
+ if( (l_mod == 3) ||
+ ((l_granulesCompleted+1) == l_lenCacheAligned) )
+ {
+ 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)
+ {
+ SBE_DEBUG("l_dataFifo#3 0x%08x%08x", SBE::higher32BWord(l_dataFifo[0]),
+ SBE::lower32BWord(l_dataFifo[0]));
+ // For lengths 1,2 and 4, data needs to be extracted from
+ // shift-aligned 8-byte address boundary.
+ l_dataFifo[0] <<= GET_8_BYTE_ALIGNED_OFFSET(l_addr);
+ SBE_DEBUG("l_dataFifo#4 0x%08x%08x", SBE::higher32BWord(l_dataFifo[0]),
+ SBE::lower32BWord(l_dataFifo[0]));
+
+ l_rc = sbeDownFifoEnq_mult (l_len, (uint32_t *)&l_dataFifo);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ }
+ }
+ l_addr += l_granuleSize;
+ l_granulesCompleted++;
+ } // End..while (l_granulesCompleted < l_lenCacheAligned);
+ } while(false);
+
+ // 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_respHdr.primaryStatus);
+ 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_granuleSize,
+ 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);
+}
+#endif //not __SBEFW_SEEPROM__
+#ifdef __SBEFW_SEEPROM__
+
+uint32_t sbeUpdateMemAccessRegion (uint8_t *i_pArg)
+{
+ #define SBE_FUNC "sbeManageMemAccessRegion"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t rc = SBE_SEC_GENERIC_FAILURE_IN_EXECUTION;
+ uint32_t fapiRc = FAPI2_RC_SUCCESS;
+ sbeMemRegionReq_t req = {};
+
+ do
+ {
+ rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1,
+ (sizeof(req)/sizeof(uint64_t)),
+ (uint64_t*)&req,
+ true);
+ if(SBE_SEC_OPERATION_SUCCESSFUL != rc)
+ {
+ SBE_ERROR(SBE_FUNC "Failed to extract SBE_HOST_PSU_MBOX_REG1 and "
+ "SBE_HOST_PSU_MBOX_REG2");
+ break;
+ }
+
+ SBE_INFO(SBE_FUNC" Addr[0x%08x%08x] size[0x%08x] flags[0x%04x]",
+ SBE::higher32BWord(req.startAddress),
+ SBE::lower32BWord(req.startAddress),
+ req.size,
+ SBE_GLOBAL->sbePsu2SbeCmdReqHdr.flags);
+
+ uint16_t mode = SBE_GLOBAL->sbePsu2SbeCmdReqHdr.flags & 0x00FF;
+ if(mode == SBE_MEM_REGION_CLOSE)
+ {
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.secStatus =
+ mainStoreSecMemRegionManager.remove(req.startAddress);
+ }
+ else
+ {
+ uint8_t memMode = 0;
+ if(mode == SBE_MEM_REGION_OPEN_RO)
+ {
+ memMode = static_cast<uint8_t>(memRegionMode::READ);
+ }
+ else if(mode == SBE_MEM_REGION_OPEN_RW)
+ {
+ memMode = static_cast<uint8_t>(memRegionMode::READ) |
+ static_cast<uint8_t>(memRegionMode::WRITE);
+ }
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.secStatus =
+ mainStoreSecMemRegionManager.add(req.startAddress,
+ req.size,
+ memMode);
+ }
+ if(SBE_GLOBAL->sbeSbe2PsuRespHdr.secStatus !=
+ SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.primStatus = SBE_PRI_USER_ERROR;
+ }
+ } while(false);
+
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, fapiRc, rc);
+
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+ #undef SBE_FUNC
+}
+#endif //__SBEFW_SEEPROM__
diff --git a/src/sbefw/core/sbecmdmemaccess.H b/src/sbefw/core/sbecmdmemaccess.H
new file mode 100644
index 00000000..54c9aa39
--- /dev/null
+++ b/src/sbefw/core/sbecmdmemaccess.H
@@ -0,0 +1,70 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdmemaccess.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdmemaccess.H
+ *
+ * @brief This file contains the Interfaces for the Memory Access chip-ops
+ *
+ */
+
+#ifndef __SBEFW_SBECMDMEMACCESS_H
+#define __SBEFW_SBECMDMEMACCESS_H
+
+#include <stdint.h>
+
+typedef struct
+{
+ uint64_t reserved:32;
+ uint64_t size:32;
+ uint64_t startAddress:64;
+} sbeMemRegionReq_t;
+
+/**
+ * @brief sbeUpdateMemAccessRegion - manage the unsecure memory regions
+ *
+ * @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 sbeUpdateMemAccessRegion (uint8_t *i_pArg);
+
+/**
+ * @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/core/sbecmdmpipl.C b/src/sbefw/core/sbecmdmpipl.C
new file mode 100644
index 00000000..3179382f
--- /dev/null
+++ b/src/sbefw/core/sbecmdmpipl.C
@@ -0,0 +1,430 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdmpipl.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/src/sbefw/sbecmdmpipl.C
+ *
+ * @brief This file contains the SBE MPIPL chipOps
+ *
+ */
+
+#include "sbefifo.H"
+#include "sbeSpMsg.H"
+#include "sbe_sp_intf.H"
+#include "sbetrace.H"
+#include "sbeFifoMsgUtils.H"
+#include "sbecmdmpipl.H"
+#include "sberegaccess.H"
+#include "sbefapiutil.H"
+#include "sbecmdiplcontrol.H"
+
+#include "p9_hcd_core_stopclocks.H"
+#include "p9_hcd_cache_stopclocks.H"
+#include "p9_stopclocks.H"
+#include "fapi2.H"
+
+using namespace fapi2;
+
+// Defines for stop clock
+#define SBE_IS_EX0(chipletId) \
+ (!(((chipletId - CORE_CHIPLET_OFFSET) & 0x0002) >> 1))
+
+/* @brief Bitmapped enumeration to identify the stop clock HWP call
+ */
+enum stopClockHWPType
+{
+ SC_NONE = 0x00,
+ SC_PROC = 0x01, // Call p9_stopclocks
+ SC_CACHE = 0x02, // Call p9_hcd_cache_stopclocks
+ SC_CORE = 0x04, // Call p9_hcd_core_stopclocks
+};
+
+#ifdef __SBEFW_SEEPROM__
+
+#ifdef SEEPROM_IMAGE
+ // Using function pointer to force long call.
+p9_hcd_cache_stopclocks_FP_t p9_hcd_cache_stopclocks_hwp = &p9_hcd_cache_stopclocks;
+p9_hcd_core_stopclocks_FP_t p9_hcd_core_stopclocks_hwp = &p9_hcd_core_stopclocks;
+p9_stopclocks_FP_t p9_stopclocks_hwp = &p9_stopclocks;
+#endif
+
+
+///////////////////////////////////////////////////////////////////////
+// @brief sbeEnterMpipl Sbe enter MPIPL function
+//
+// @return RC from the underlying FIFO utility
+///////////////////////////////////////////////////////////////////////
+uint32_t sbeEnterMpipl(uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbeEnterMpipl "
+ SBE_ENTER(SBE_FUNC);
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t l_fapiRc = FAPI2_RC_SUCCESS;
+ uint32_t len = 0;
+ sbeRespGenHdr_t l_respHdr;
+ l_respHdr.init();
+ sbeResponseFfdc_t l_ffdc;
+
+ do
+ {
+ // Dequeue the EOT entry as no more data is expected.
+ l_rc = sbeUpFifoDeq_mult (len, NULL);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+
+ uint32_t l_minor = 1;
+ do
+ {
+ l_fapiRc = sbeExecuteIstep(SBE_ISTEP_MPIPL_START, l_minor);
+ if(l_fapiRc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC "Failed in Mpipl Start in ChipOp Mode "
+ "Minor: %d", l_minor);
+ l_respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ l_ffdc.setRc(l_fapiRc);
+ // reset attribute. We do not want to reset register, so do not
+ // use setMpIplMode
+ uint8_t isMpipl = 0;
+ PLAT_ATTR_INIT(ATTR_IS_MPIPL, Target<TARGET_TYPE_SYSTEM>(),
+ isMpipl);
+ break;
+ }
+ ++l_minor;
+ }while(l_minor<=MPIPL_START_MAX_SUBSTEPS);
+
+ }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
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ l_rc = sbeDsSendRespHdr( l_respHdr, &l_ffdc);
+ }while(0);
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+///////////////////////////////////////////////////////////////////////
+// @brief sbeContinueMpipl Sbe Continue MPIPL function
+//
+// @return RC from the underlying FIFO utility
+///////////////////////////////////////////////////////////////////////
+uint32_t sbeContinueMpipl(uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbeContinueMpipl "
+ SBE_ENTER(SBE_FUNC);
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t len = 0;
+
+ ReturnCode l_fapiRc = FAPI2_RC_SUCCESS;
+ sbeResponseFfdc_t l_ffdc;
+ sbeRespGenHdr_t l_respHdr;
+ l_respHdr.init();
+
+ do
+ {
+ // Dequeue the EOT entry as no more data is expected.
+ l_rc = sbeUpFifoDeq_mult (len, NULL);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+
+ sbeRole l_sbeRole = SbeRegAccess::theSbeRegAccess().isSbeSlave() ?
+ SBE_ROLE_SLAVE : SBE_ROLE_MASTER;
+ // Run isteps
+ const uint8_t isteps[][3] = {
+ // Major Num, Minor Start, Minor End
+ {SBE_ISTEP_MPIPL_CONTINUE, ISTEP_MINOR_START, MPIPL_CONTINUE_MAX_SUBSTEPS},
+ {SBE_ISTEP4, ISTEP_MINOR_START, ISTEP4_MAX_SUBSTEPS},
+ {SBE_ISTEP5, ISTEP_MINOR_START, ISTEP5_MAX_SUBSTEPS}};
+ // Loop through isteps
+ for( auto istep : isteps)
+ {
+ // This is required here to skip the major istep 4/5 in slave
+ if((SBE_ROLE_SLAVE == l_sbeRole) &&
+ (istep[0] == SBE_ISTEP4 || istep[0] == SBE_ISTEP5))
+ {
+ (void)SbeRegAccess::theSbeRegAccess().stateTransition(
+ SBE_RUNTIME_EVENT);
+ continue;
+ }
+ for(uint8_t l_minor = istep[1]; l_minor <= istep[2]; l_minor++)
+ {
+ l_fapiRc = sbeExecuteIstep(istep[0], l_minor);
+ if(l_fapiRc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC "Failed in Mpipl continue in ChipOp "
+ "Mode Major [%d] Minor [%d]", istep[0], l_minor);
+ l_respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ l_ffdc.setRc(l_fapiRc);
+ break;
+ }
+ }
+ if(l_ffdc.getRc() != FAPI2_RC_SUCCESS)
+ {
+ break;
+ }
+ }
+ }while(0);
+
+ // reset attribute. We do not want to reset register, so do not
+ // use setMpIplMode
+ uint8_t isMpipl = 0;
+ PLAT_ATTR_INIT(ATTR_IS_MPIPL, Target<TARGET_TYPE_SYSTEM>(), isMpipl);
+ // Create the Response to caller
+ // 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_rc = sbeDsSendRespHdr( l_respHdr, &l_ffdc);
+ }
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+///////////////////////////////////////////////////////////////////////
+/* @brief Deduce the type of stop clock procedure to call based on
+ * target and chiplet id combination
+ *
+ * @param[in] i_targetType SBE chip-op target type
+ * @param[in] i_chipletId Chiplet id
+ *
+ * @return Bitmapped stopClockHWPType enum values
+ */
+///////////////////////////////////////////////////////////////////////
+static inline uint32_t getStopClockHWPType(uint32_t i_targetType,
+ uint32_t i_chipletId)
+{
+ uint32_t l_rc = SC_NONE;
+ TargetType l_fapiTarget = sbeGetFapiTargetType(
+ i_targetType,
+ i_chipletId);
+ if((l_fapiTarget == TARGET_TYPE_PROC_CHIP) ||
+ (l_fapiTarget == TARGET_TYPE_PERV) ||
+ ((i_targetType == TARGET_CORE) && (i_chipletId == SMT4_ALL_CORES))||
+ ((i_targetType == TARGET_EQ) && (i_chipletId == EQ_ALL_CHIPLETS)) ||
+ ((i_targetType == TARGET_EX) && (i_chipletId == EX_ALL_CHIPLETS)))
+ {
+ l_rc |= SC_PROC;
+ }
+ if((l_fapiTarget == TARGET_TYPE_CORE) ||
+ (l_fapiTarget == TARGET_TYPE_EX))
+ {
+ l_rc |= SC_CORE;
+ }
+ if((l_fapiTarget == TARGET_TYPE_EQ) ||
+ (l_fapiTarget == TARGET_TYPE_EX))
+ {
+ l_rc |= SC_CACHE;
+ }
+ return l_rc;
+}
+
+///////////////////////////////////////////////////////////////////////
+/* @brief Prepare Stop clock flags base on Target Type
+ *
+ * @param[in] i_targetType SBE chip-op target Type
+ *
+ * @return p9_stopclocks_flags
+ */
+///////////////////////////////////////////////////////////////////////
+static inline p9_stopclocks_flags getStopClocksFlags(uint32_t i_targetType)
+{
+ p9_stopclocks_flags l_flags;
+
+ if(i_targetType != TARGET_PROC_CHIP)
+ {
+ // Clear default flags - only in case the target is not PROC_CHIP
+ // Otherwise, for a PROC_CHIP target, we want to keep default flags
+ l_flags.clearAll();
+ }
+ if(i_targetType == TARGET_PERV)
+ {
+ // Keep only tp as true
+ l_flags.stop_tp_clks = true;
+ }
+ else if(i_targetType == TARGET_CORE)
+ {
+ // Keep only core flag as true
+ l_flags.stop_core_clks = true;
+ }
+ else if(i_targetType == TARGET_EQ)
+ {
+ // Keep only cache flag as true
+ l_flags.stop_cache_clks = true;
+ }
+ else if(i_targetType == TARGET_EX)
+ {
+ // Keep only cache and core as true
+ l_flags.stop_cache_clks = true;
+ l_flags.stop_core_clks = true;
+ }
+
+ return l_flags;
+}
+
+///////////////////////////////////////////////////////////////////////
+// @brief sbeStopClocks Sbe Stop Clocks function
+//
+// @return RC from the underlying FIFO utility
+///////////////////////////////////////////////////////////////////////
+uint32_t sbeStopClocks(uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbeStopClocks"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t l_fapiRc = FAPI2_RC_SUCCESS;
+ uint32_t l_len = 0;
+ sbeResponseFfdc_t l_ffdc;
+ sbeRespGenHdr_t l_respHdr;
+ l_respHdr.init();
+ sbeStopClocksReqMsgHdr_t l_reqMsg = {0};
+
+ do
+ {
+ // Get the TargetType and ChipletId from the command message
+ l_len = sizeof(sbeStopClocksReqMsgHdr_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 "TargetType 0x%04X ChipletId 0x%02X",
+ (uint16_t)l_reqMsg.targetType,
+ (uint8_t)l_reqMsg.chipletId);
+
+ fapi2::plat_target_handle_t l_tgtHndl;
+ // Keep these default values in sync with p9_stopclocks.H
+ p9hcd::P9_HCD_CLK_CTRL_CONSTANTS l_clk_regions
+ = p9hcd::CLK_REGION_ALL_BUT_PLL_REFR;
+ p9hcd::P9_HCD_EX_CTRL_CONSTANTS l_ex_select = p9hcd::BOTH_EX;
+
+ // Get the type of stopclocks procedure to call
+ // based on target and chiplet id
+ uint32_t l_hwpType = getStopClockHWPType(l_reqMsg.targetType,
+ l_reqMsg.chipletId);
+ if(l_hwpType == SC_NONE)
+ {
+ // Error in target and chiplet id combination
+ SBE_ERROR(SBE_FUNC "Invalid TargetType[0x%04X] ChipletId[0x%02X]",
+ (uint32_t)l_reqMsg.targetType,
+ (uint32_t)l_reqMsg.chipletId);
+ l_respHdr.setStatus( SBE_PRI_INVALID_DATA,
+ SBE_SEC_INVALID_TARGET_TYPE_PASSED );
+ break;
+ }
+ // All Core/All Cache/All Ex & Perv & Proc are handled here
+ if(l_hwpType & SC_PROC)
+ {
+ SBE_DEBUG(SBE_FUNC " Calling p9_stopclocks");
+ p9_stopclocks_flags l_flags = getStopClocksFlags(
+ l_reqMsg.targetType);
+ if(l_reqMsg.targetType == TARGET_EX)
+ {
+ l_clk_regions = static_cast<p9hcd::P9_HCD_CLK_CTRL_CONSTANTS>
+ (p9hcd::CLK_REGION_EX0_REFR |
+ p9hcd::CLK_REGION_EX1_REFR);
+ }
+ l_flags.sync_stop_quad_clks = false;
+ SBE_EXEC_HWP(l_fapiRc, p9_stopclocks_hwp,
+ plat_getChipTarget(),
+ l_flags,
+ l_clk_regions,
+ l_ex_select);
+ }
+ // Specific CORE/EX
+ if(l_hwpType & SC_CORE)
+ {
+ SBE_DEBUG(SBE_FUNC " Calling p9_hcd_core_stopclocks");
+ sbeGetFapiTargetHandle(l_reqMsg.targetType,
+ l_reqMsg.chipletId,
+ l_tgtHndl);
+ if(l_reqMsg.targetType == TARGET_EX)
+ {
+ Target<TARGET_TYPE_EX> l_exTgt(l_tgtHndl);
+ for(auto &l_childCore :
+ l_exTgt.getChildren<TARGET_TYPE_CORE>())
+ {
+ SBE_EXEC_HWP(l_fapiRc,
+ p9_hcd_core_stopclocks_hwp,
+ l_childCore,
+ false);
+ }
+ }
+ else
+ {
+ SBE_EXEC_HWP(l_fapiRc, p9_hcd_core_stopclocks_hwp, l_tgtHndl, false);
+ }
+ }
+ // Specific EQ/EX
+ if(l_hwpType & SC_CACHE)
+ {
+ SBE_DEBUG(SBE_FUNC " Calling p9_hcd_cache_stopclocks");
+ if(l_reqMsg.targetType == TARGET_EX)
+ {
+ // Modify l_clk_regions based on chiplet Id
+ l_clk_regions = SBE_IS_EX0(l_reqMsg.chipletId) ?
+ p9hcd::CLK_REGION_EX0_REFR : p9hcd::CLK_REGION_EX1_REFR;
+ // Modify l_ex_select based on chiplet ID
+ l_ex_select = SBE_IS_EX0(l_reqMsg.chipletId) ?
+ p9hcd::EVEN_EX : p9hcd::ODD_EX;
+ Target<TARGET_TYPE_EX> l_ex_target(l_tgtHndl);
+ l_tgtHndl = l_ex_target.getParent<TARGET_TYPE_EQ>();
+ }
+ SBE_EXEC_HWP(l_fapiRc, p9_hcd_cache_stopclocks_hwp,
+ l_tgtHndl,
+ (p9hcd::P9_HCD_CLK_CTRL_CONSTANTS)l_clk_regions,
+ (p9hcd::P9_HCD_EX_CTRL_CONSTANTS)l_ex_select,
+ false);
+ }
+
+ if( l_fapiRc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" Stopclocks failed for TargetType [0x%04X] "
+ "ChipletId [0x%02X]",
+ (uint16_t)l_reqMsg.targetType,
+ (uint8_t)l_reqMsg.chipletId);
+ l_respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ l_ffdc.setRc(l_fapiRc);
+ break;
+ }
+ }while(0);
+
+ // Create the Response to caller
+ // 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_rc = sbeDsSendRespHdr( l_respHdr, &l_ffdc);
+ }
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+#endif //__SBEFW_SEEPROM__
diff --git a/src/sbefw/core/sbecmdmpipl.H b/src/sbefw/core/sbecmdmpipl.H
new file mode 100644
index 00000000..0acb3efd
--- /dev/null
+++ b/src/sbefw/core/sbecmdmpipl.H
@@ -0,0 +1,63 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdmpipl.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/src/sbefw/sbecmdmpipl.H
+ *
+ * @brief This file contains the Interfaces for MPIPL chip-ops
+ *
+ */
+
+#ifndef __SBEFW_SBECMDMPIPL_H
+#define __SBEFW_SBECMDMPIPL_H
+
+#include <stdint.h>
+
+/**
+ * @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 Stop Clocks chip-op (0xA903)
+ *
+ * @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 sbeStopClocks(uint8_t *i_pArg);
+
+#endif /* __SBEFW_SBECMDMPIPL_H */
diff --git a/src/sbefw/core/sbecmdparser.C b/src/sbefw/core/sbecmdparser.C
new file mode 100644
index 00000000..1671f8a3
--- /dev/null
+++ b/src/sbefw/core/sbecmdparser.C
@@ -0,0 +1,603 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdparser.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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"
+#include "sbecmdmpipl.H"
+#include "sbecmdtracearray.H"
+#include "sbecmdCntrlTimer.H"
+#include "sbecmdfastarray.H"
+#include "sbeglobals.H"
+
+// Declaration
+static const uint16_t HARDWARE_FENCED_STATE =
+ SBE_FENCE_AT_CONTINUOUS_IPL|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,
+ },
+ {sbePutScom,
+ SBE_CMD_PUTSCOM,
+ HARDWARE_FENCED_STATE,
+ },
+ {sbeModifyScom,
+ SBE_CMD_MODIFYSCOM,
+ HARDWARE_FENCED_STATE,
+ },
+ {sbePutScomUnderMask,
+ SBE_CMD_PUTSCOM_MASK,
+ HARDWARE_FENCED_STATE,
+ },
+ {sbeMultiScom,
+ SBE_CMD_MULTISCOM,
+ HARDWARE_FENCED_STATE,
+ },
+};
+
+////////////////////////////////////////////////////////////////
+// @brief g_sbeIplControlCmdArray
+//
+////////////////////////////////////////////////////////////////
+static sbeCmdStruct_t g_sbeIplControlCmdArray [] =
+{
+ {sbeHandleIstep,
+ SBE_CMD_EXECUTE_ISTEP,
+ HARDWARE_FENCED_STATE|SBE_FENCE_AT_DUMPING,
+ },
+ {sbeHandleSuspendIO,
+ SBE_CMD_SUSPEND_IO,
+ SBE_FENCE_AT_DUMPING,
+ },
+};
+
+////////////////////////////////////////////////////////////////
+// @brief g_sbeGenericCmdArray
+//
+////////////////////////////////////////////////////////////////
+static sbeCmdStruct_t g_sbeGenericCmdArray [] =
+{
+ {sbeGetCapabilities,
+ SBE_CMD_GET_SBE_CAPABILITIES,
+ SBE_NO_FENCE,
+ },
+
+ {sbeGetFfdc,
+ SBE_CMD_GET_SBE_FFDC,
+ SBE_NO_FENCE,
+ },
+
+ {sbeFifoQuiesce,
+ SBE_CMD_QUIESCE,
+ SBE_NO_FENCE,
+ },
+};
+
+//////////////////////////////////////////////////////////////
+// @brief g_sbeMemoryAccessCmdArray
+//
+//////////////////////////////////////////////////////////////
+static sbeCmdStruct_t g_sbeMemoryAccessCmdArray [] =
+{
+ {sbeGetMem,
+ SBE_CMD_GETMEM,
+ SBE_FENCE_AT_CONTINUOUS_IPL,
+ },
+
+ {sbePutMem,
+ SBE_CMD_PUTMEM,
+ PUT_HARDWARE_FENCED_STATE,
+ },
+
+ {sbeGetOccSram,
+ SBE_CMD_GETSRAM_OCC,
+ HARDWARE_FENCED_STATE,
+ },
+
+ {sbePutOccSram,
+ SBE_CMD_PUTSRAM_OCC,
+ PUT_HARDWARE_FENCED_STATE,
+ },
+};
+
+//////////////////////////////////////////////////////////////
+// @brief g_sbeInstructionCntlCmdArray
+//
+//////////////////////////////////////////////////////////////
+static sbeCmdStruct_t g_sbeInstructionCntlCmdArray[] =
+{
+ {sbeCntlInst,
+ SBE_CMD_CONTROL_INSTRUCTIONS,
+ HARDWARE_FENCED_STATE,
+ },
+};
+
+//////////////////////////////////////////////////////////////
+// @brief g_sbeRegAccessCmdArray
+//
+//////////////////////////////////////////////////////////////
+static sbeCmdStruct_t g_sbeRegAccessCmdArray [] =
+{
+ {sbeGetReg,
+ SBE_CMD_GETREG,
+ HARDWARE_FENCED_STATE,
+ },
+
+ {sbePutReg,
+ SBE_CMD_PUTREG,
+ PUT_HARDWARE_FENCED_STATE | SBE_FENCE_AT_SECURE_MODE,
+ },
+};
+
+//////////////////////////////////////////////////////////////
+// @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,
+ // Allow Fspless system to enter MPIPL
+ // Issue 157287
+ },
+
+ {sbeContinueMpipl,
+ SBE_CMD_MPIPL_CONTINUE,
+ HARDWARE_FENCED_STATE|SBE_FENCE_AT_ISTEP|
+ SBE_FENCE_AT_RUNTIME|SBE_FENCE_AT_DUMPING,
+ // Only allowed State is MPIPL
+ },
+
+ {sbeStopClocks,
+ SBE_CMD_MPIPL_STOPCLOCKS,
+ HARDWARE_FENCED_STATE|SBE_FENCE_AT_DUMPING,
+ },
+};
+
+//////////////////////////////////////////////////////////////
+// @brief g_sbeRingAccessCmdArray
+//
+//////////////////////////////////////////////////////////////
+static sbeCmdStruct_t g_sbeRingAccessCmdArray [] =
+{
+ {sbeGetRing,
+ SBE_CMD_GETRING,
+ SBE_FENCE_AT_CONTINUOUS_IPL|SBE_FENCE_AT_QUIESCE,
+ },
+
+ {sbePutRing,
+ SBE_CMD_PUTRING,
+ HARDWARE_FENCED_STATE|SBE_FENCE_AT_QUIESCE,
+ },
+};
+
+// @brief g_sbeArrayAccessCmdArray[]
+//
+////////////////////////////////////////////////////////////////
+static sbeCmdStruct_t g_sbeArrayAccessCmdArray[] =
+{
+ {sbeControlFastArray,
+ SBE_CMD_CONTROL_FAST_ARRAY,
+ SBE_FENCE_AT_QUIESCE,
+ },
+ {sbeControlTraceArray,
+ SBE_CMD_CONTROL_TRACE_ARRAY,
+ SBE_FENCE_AT_QUIESCE,
+ },
+};
+
+//////////////////////////////////////////////////////////////
+// @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,
+ },
+};
+
+//////////////////////////////////////////////////////////////
+// @brief g_sbeControlTimerCmdArray
+//
+//////////////////////////////////////////////////////////////
+static sbeCmdStruct_t g_sbeControlTimerCmdArray [] =
+{
+ {sbeCntrlTimer,
+ SBE_PSU_CMD_CONTROL_TIMER,
+ SBE_FENCE_AT_CONTINUOUS_IPL|SBE_FENCE_AT_QUIESCE|
+ SBE_FENCE_AT_MPIPL|SBE_FENCE_AT_DUMPING,
+ },
+};
+
+//////////////////////////////////////////////////////////////
+// @brief g_sbePutRingFromImageCmdArray
+//
+//////////////////////////////////////////////////////////////
+static sbeCmdStruct_t g_sbePutRingFromImageCmdArray [] =
+{
+ {sbePutRingFromImagePSU,
+ SBE_PSU_MSG_PUT_RING_FROM_IMAGE,
+ PUT_HARDWARE_FENCED_STATE|SBE_FENCE_AT_QUIESCE,
+ },
+};
+//
+//////////////////////////////////////////////////////////////
+// @brief g_sbePsuGenericCmdArray
+//
+//////////////////////////////////////////////////////////////
+static sbeCmdStruct_t g_sbePsuMemRegionCmdArray[] =
+{
+ {sbeUpdateMemAccessRegion,
+ SBE_PSU_MSG_UPDATE_MEM_REGION,
+ SBE_FENCE_AT_QUIESCE,
+ },
+};
+
+//////////////////////////////////////////////////////////////
+// @brief g_sbePsuGenericCmdArray
+//
+//////////////////////////////////////////////////////////////
+static sbeCmdStruct_t g_sbePsuGenericCmdArray[] =
+{
+ {sbeReadMem,
+ SBE_PSU_GENERIC_MSG_READ_SBE_MEM,
+ SBE_NO_FENCE,
+ },
+
+ {sbeSetFFDCAddr,
+ SBE_PSU_GENERIC_MSG_SET_FFDC_ADDR,
+ SBE_NO_FENCE,
+ },
+
+ {sbePsuQuiesce,
+ SBE_PSU_GENERIC_MSG_QUIESCE,
+ SBE_NO_FENCE,
+ },
+
+ {sbeSetSystemFabricMap,
+ SBE_PSU_GENERIC_MSG_SYSTEM_FABRIC_MAP,
+ SBE_NO_FENCE,
+ },
+
+ {sbeStashKeyAddrPair,
+ SBE_PSU_GENERIC_MSG_STASH_MPIPL_CONFIG,
+ SBE_NO_FENCE,
+ },
+};
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+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;
+
+ case SBE_CMD_CLASS_ARRAY_ACCESS:
+ l_numCmds = sizeof(g_sbeArrayAccessCmdArray) /
+ sizeof(sbeCmdStruct_t);
+ *o_ppCmd = (sbeCmdStruct_t*)g_sbeArrayAccessCmdArray;
+ 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;
+
+ case SBE_PSU_CMD_CLASS_GENERIC:
+ l_numCmds = sizeof(g_sbePsuGenericCmdArray) /
+ sizeof(sbeCmdStruct_t);
+ *o_ppCmd = (sbeCmdStruct_t*)g_sbePsuGenericCmdArray;
+ break;
+
+ case SBE_PSU_CMD_CLASS_SECURITY_CONTROL_MSG:
+ l_numCmds = sizeof(g_sbePsuMemRegionCmdArray) /
+ sizeof(sbeCmdStruct_t);
+ *o_ppCmd = (sbeCmdStruct_t*)g_sbePsuMemRegionCmdArray;
+ break;
+
+ case SBE_PSU_CMD_CLASS_CNTRL_TIMER:
+ l_numCmds = sizeof(g_sbeControlTimerCmdArray) /
+ sizeof(sbeCmdStruct_t);
+ *o_ppCmd = (sbeCmdStruct_t*)g_sbeControlTimerCmdArray;
+ 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
+}
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+sbeChipOpRc_t sbeIsCmdAllowed (const uint8_t i_cmdClass,
+ const uint8_t i_cmdOpcode)
+{
+ #define SBE_FUNC " sbeIsCmdAllowedAtState "
+ bool l_ret = true;
+ sbeChipOpRc_t retRc;
+ 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)
+ {
+ // 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_UNKNOWN:
+ case SBE_STATE_FAILURE:
+ // All operations are fenced here, return false
+ // Reset is the only Option available
+ 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_QUIESCE:
+ {
+ l_ret = ((l_pCmd->cmd_state_fence &
+ SBE_FENCE_AT_QUIESCE)? false:true);
+ break;
+ }
+
+ default:
+ l_ret = false;
+ break;
+ }
+
+ if(false == l_ret)
+ {
+ retRc.primStatus = SBE_PRI_INVALID_COMMAND;
+ retRc.secStatus = SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE;
+ break;
+ }
+ // Check if the command is allowed in current security mode
+ if((SBE_GLOBAL->sbeFWSecurityEnabled)
+ && (SBE_FENCE_AT_SECURE_MODE & l_pCmd->cmd_state_fence))
+ {
+ retRc.primStatus = SBE_PRI_UNSECURE_ACCESS_DENIED;
+ retRc.secStatus = SBE_SEC_BLACKLISTED_CHIPOP_ACCESS;
+ break;
+ }
+ break;
+ }
+ }
+ return retRc;
+ #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/core/sbecmdparser.H b/src/sbefw/core/sbecmdparser.H
new file mode 100644
index 00000000..3d90c007
--- /dev/null
+++ b/src/sbefw/core/sbecmdparser.H
@@ -0,0 +1,135 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdparser.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdparser.H
+ *
+ * @brief This file contains the SBE command details
+ *
+ */
+
+#ifndef __SBEFW_SBECMDPARSER_H
+#define __SBEFW_SBECMDPARSER_H
+
+#include <stdint.h>
+#include "sbe_sp_intf.H"
+
+// Chip-op response codes
+typedef struct sbeChipOpRc
+{
+ sbePrimResponse primStatus;
+ sbeSecondaryResponse secStatus;
+
+ sbeChipOpRc():primStatus(SBE_PRI_OPERATION_SUCCESSFUL),
+ secStatus(SBE_SEC_OPERATION_SUCCESSFUL)
+ {}
+
+ bool success()
+ {
+ return (primStatus == SBE_PRI_OPERATION_SUCCESSFUL) &&
+ (secStatus == SBE_SEC_OPERATION_SUCCESSFUL);
+ }
+} sbeChipOpRc_t;
+
+/**
+ * @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 sbeCmdStruct {
+ 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_DUMPING = 0x0001, ///< Fence off at DUMPING State
+ SBE_FENCE_AT_MPIPL = 0x0002, ///< Fence off at MPIPL state
+ SBE_FENCE_AT_CONTINUOUS_IPL = 0x0004, ///< Fence off at cont IPL
+ SBE_FENCE_AT_ISTEP = 0x0008, ///< Fence off at istep state
+ SBE_FENCE_AT_RUNTIME = 0x0010, ///< Fence off at Runtime state
+ SBE_FENCE_AT_QUIESCE = 0x0020, ///< Fense off at Quiesce state
+ SBE_FENCE_AT_DMT = 0x0040, ///< Fense off at DMT state
+ SBE_FENCE_AT_SECURE_MODE = 0x0080, ///< Fense off in secure mode
+};
+
+/**
+ * @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 sbeIsCmdAllowed 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 sbeChipOpRc_t Indicating primary and secondary status of
+ * chip-op
+ */
+sbeChipOpRc_t sbeIsCmdAllowed (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/core/sbecmdprocessor.C b/src/sbefw/core/sbecmdprocessor.C
new file mode 100644
index 00000000..aacf892a
--- /dev/null
+++ b/src/sbefw/core/sbecmdprocessor.C
@@ -0,0 +1,397 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdprocessor.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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"
+#include "sbeutil.H"
+#include "sbeglobals.H"
+using namespace fapi2;
+
+// Forward declaration for performAttrSetup
+ReturnCode performAttrSetup( );
+
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+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:
+ case SBE_SEC_BLACKLISTED_CHIPOP_ACCESS:
+ // 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
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INVALID_COMMAND, i_rc);
+
+ // Now Update SBE->PSU Mbx Reg4 with response
+ l_cnt = sizeof(SBE_GLOBAL->sbeSbe2PsuRespHdr)/
+ sizeof(uint64_t);
+ l_rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4,
+ reinterpret_cast<const uint64_t *>(
+ &SBE_GLOBAL->sbeSbe2PsuRespHdr), l_cnt, true);
+ break;
+
+ case SBE_SEC_OS_FAILURE:
+ // Set primary and secondary status
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ i_rc);
+
+ // Now Update SBE->PSU Mbx Reg4 with response
+ l_cnt = sizeof(SBE_GLOBAL->sbeSbe2PsuRespHdr)/
+ sizeof(uint64_t);
+ l_rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4,
+ reinterpret_cast<const uint64_t *>(
+ &SBE_GLOBAL->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;
+ sbeRespGenHdr_t l_hdr;
+ l_hdr.init();
+ 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:
+ case SBE_SEC_BLACKLISTED_CHIPOP_ACCESS:
+ // 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);
+ l_hdr.setStatus(l_primStatus, l_secStatus);
+
+ l_rc = sbeDsSendRespHdr(l_hdr);
+ 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
+}
+
+ReturnCode sbeDestRuntimeSetup()
+{
+ #define SBE_FUNC " sbeDestRuntimeSetup "
+ SBE_ENTER( SBE_FUNC );
+ ReturnCode rc = FAPI2_RC_SUCCESS;
+ do
+ {
+ rc = performAttrSetup();
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC"performAttrSetup failed");
+ break;
+ }
+ SBE::updatePkFreq();
+ }while(0);
+ SBE_EXIT("SBE_FUNC");
+ return rc;
+ #undef SBE_FUNC
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+void sbeSyncCommandProcessor_routine(void *i_pArg)
+{
+ #define SBE_FUNC " sbeSyncCommandProcessor_routine "
+ SBE_ENTER(SBE_FUNC);
+
+ // Update SBE msgg reg to indicate that control loop
+ // is ready now to receive data on its interfaces
+ (void)SbeRegAccess::theSbeRegAccess().setSbeReady();
+
+ // Check the destination bit at the start
+ if(true == SbeRegAccess::theSbeRegAccess().isDestBitRuntime())
+ {
+ SBE_INFO(SBE_FUNC"Destination bit tells us to go to runtime");
+ (void)SbeRegAccess::theSbeRegAccess().
+ updateSbeState(SBE_STATE_RUNTIME);
+ // Do the runtime setup
+ ReturnCode rc = sbeDestRuntimeSetup();
+ if( rc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC"sbeDestRuntimeSetup failed");
+ pk_halt();
+ }
+ }
+ else if(SbeRegAccess::theSbeRegAccess().isIstepMode())
+ {
+ SBE_INFO(SBE_FUNC"Continuous IPL mode not set, will wait for "
+ "commands...");
+ (void)SbeRegAccess::theSbeRegAccess().
+ updateSbeState(SBE_STATE_ISTEP);
+ }
+ 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 (
+ &SBE_GLOBAL->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 ( SBE_GLOBAL->sbeIntrSource.isSet(SBE_RX_ROUTINE,
+ SBE_INTERFACE_PSU) )
+ {
+ l_rc = SBE_GLOBAL->sbeSbe2PsuRespHdr.secStatus;
+ l_cmdClass = SBE_GLOBAL->sbePsu2SbeCmdReqHdr.cmdClass;
+ l_cmdOpCode = SBE_GLOBAL->sbePsu2SbeCmdReqHdr.command;
+ // Set this here, so that during response handling we know which
+ // interrupt we are processing, need not check for
+ // SBE_GLOBAL->sbeIntrSource again
+ SBE_GLOBAL->sbeIntrSource.setIntrSource(SBE_PROC_ROUTINE,
+ SBE_INTERFACE_PSU);
+ }
+ else if ( SBE_GLOBAL->sbeIntrSource.isSet(SBE_RX_ROUTINE,
+ SBE_INTERFACE_FIFO) )
+ {
+ l_rc = SBE_GLOBAL->sbeCmdRespHdr.sec_status;
+ l_cmdClass = SBE_GLOBAL->sbeFifoCmdHdr.cmdClass;
+ l_cmdOpCode = SBE_GLOBAL->sbeFifoCmdHdr.command;
+ SBE_INFO(SBE_FUNC"Processing command from client :0x%01X",
+ (uint32_t)(SBE_GLOBAL->sbeFifoCmdHdr.clientId));
+ // Set this here, so that during response handling we know which
+ // interrupt we are processing, need not check for
+ // SBE_GLOBAL->sbeIntrSource again
+ SBE_GLOBAL->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",
+ SBE_GLOBAL->sbeIntrSource.intrSource, SBE_GLOBAL->sbeIntrSource.rxThrIntrSource);
+ assert(false);
+ break;
+ }
+
+ // PK API failure
+ if (l_rcPk != PK_OK)
+ {
+ SBE_ERROR(SBE_FUNC"pk_semaphore_pend failed, "
+ "l_rcPk=%d, SBE_GLOBAL->sbeSemCmdRecv.count=%d",
+ l_rcPk, SBE_GLOBAL->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"Command processesed. l_rc=[0x%04X]", l_rc );
+
+ if ( SBE_GLOBAL->sbeIntrSource.isSet(SBE_PROC_ROUTINE, SBE_INTERFACE_PSU) )
+ {
+ sbeHandlePsuResponse (l_rc);
+
+ // Enable Host interrupt
+ SBE_GLOBAL->sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER,SBE_INTERFACE_PSU);
+ pk_irq_enable(SBE_IRQ_HOST_PSU_INTR);
+ }
+ else if ( SBE_GLOBAL->sbeIntrSource.isSet(SBE_PROC_ROUTINE, SBE_INTERFACE_FIFO) )
+ {
+ sbeHandleFifoResponse (l_rc);
+
+ // Enable the new data available interrupt
+ SBE_GLOBAL->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/core/sbecmdreceiver.C b/src/sbefw/core/sbecmdreceiver.C
new file mode 100644
index 00000000..ca716c65
--- /dev/null
+++ b/src/sbefw/core/sbecmdreceiver.C
@@ -0,0 +1,308 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdreceiver.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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"
+#include "sbeglobals.H"
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+void sbeCommandReceiver_routine(void *i_pArg)
+{
+ #define SBE_FUNC " sbeCommandReceiver_routine "
+ SBE_ENTER(SBE_FUNC);
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ sbeInterfaceSrc_t curInterface = SBE_INTERFACE_UNKNOWN;
+
+ // 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 (&SBE_GLOBAL->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 ( SBE_GLOBAL->sbeIntrSource.isSet(SBE_INTERRUPT_ROUTINE,
+ SBE_INTERFACE_FIFO_RESET) )
+ {
+ SBE_ERROR(SBE_FUNC"FIFO reset received");
+ l_rc = SBE_FIFO_RESET_RECEIVED;
+ curInterface = SBE_INTERFACE_FIFO_RESET;
+ break;
+ }
+
+ // Received PSU interrupt
+ if ( SBE_GLOBAL->sbeIntrSource.isSet(SBE_INTERRUPT_ROUTINE,
+ SBE_INTERFACE_PSU) )
+ {
+ //Clear the Interrupt Source bit for PSU
+ SBE_GLOBAL->sbeIntrSource.clearIntrSource(SBE_INTERRUPT_ROUTINE,
+ SBE_INTERFACE_PSU);
+ curInterface = SBE_INTERFACE_PSU;
+ // First clear PSU->SBE DB bit 0
+ l_rc = sbeClearPsu2SbeDbBitX(SBE_PSU2SBE_DOORBELL_CLEAR_BIT0);
+ if (l_rc)
+ {
+ break;
+ }
+
+ // Initialize the SBE_GLOBAL->sbePsu2SbeCmdReqHdr
+ SBE_GLOBAL->sbePsu2SbeCmdReqHdr.init();
+ // Read the request field from PSU->SBE Mbx Reg0
+ uint8_t l_cnt = sizeof(SBE_GLOBAL->sbePsu2SbeCmdReqHdr)/sizeof(uint64_t);
+
+ l_rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG0, l_cnt,
+ (uint64_t *)&SBE_GLOBAL->sbePsu2SbeCmdReqHdr);
+
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.init();
+ l_cmdClass = SBE_GLOBAL->sbePsu2SbeCmdReqHdr.cmdClass;
+ l_command = SBE_GLOBAL->sbePsu2SbeCmdReqHdr.command;
+ } // end if loop for PSU interface chipOp handling
+
+ // Received FIFO New Data interrupt
+ else if ( SBE_GLOBAL->sbeIntrSource.isSet(SBE_INTERRUPT_ROUTINE,
+ SBE_INTERFACE_FIFO) )
+ {
+ //Clear the Interrupt Source bit for FIFO
+ SBE_GLOBAL->sbeIntrSource.clearIntrSource(SBE_INTERRUPT_ROUTINE,
+ SBE_INTERFACE_FIFO);
+ curInterface = 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 SBE_GLOBAL->sbeCmdRespHdr.prim_status
+ // and SBE_GLOBAL->sbeCmdRespHdr.sec_status for command processor thread
+ // to handle them later in the sequence.
+
+ SBE_GLOBAL->sbeFifoCmdHdr.cmdClass = SBE_CMD_CLASS_UNKNOWN;
+ SBE_GLOBAL->sbeCmdRespHdr.init();
+ uint32_t len = sizeof(SBE_GLOBAL->sbeFifoCmdHdr)/sizeof(uint32_t);
+ l_rc = sbeUpFifoDeq_mult ( len, (uint32_t *)&SBE_GLOBAL->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);
+ SBE_GLOBAL->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 = SBE_GLOBAL->sbeFifoCmdHdr.cmdClass;
+ l_command = SBE_GLOBAL->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 ( SBE_INTERFACE_PSU == curInterface )
+ {
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INVALID_COMMAND,l_rc);
+ }
+ else if ( SBE_INTERFACE_FIFO == curInterface )
+ {
+ SBE_GLOBAL->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.
+ sbeChipOpRc_t cmdAllowedStatus = sbeIsCmdAllowed(l_cmdClass, l_command);
+ if( !cmdAllowedStatus.success() && !SBE::isSimicsRunning() )
+ {
+ SBE_ERROR("Chip-Op CmdClass[0x%02X] Cmd[0x%02X] not allowed "
+ "secondary status[0x%04X] State - [0x%02X]",
+ l_cmdClass,l_command,
+ cmdAllowedStatus.secStatus,
+ SbeRegAccess::theSbeRegAccess().getSbeState());
+
+ if ( SBE_INTERFACE_PSU == curInterface )
+ {
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(cmdAllowedStatus.primStatus,
+ cmdAllowedStatus.secStatus);
+ }
+ else if ( SBE_INTERFACE_FIFO == curInterface )
+ {
+ SBE_GLOBAL->sbeCmdRespHdr.setStatus(cmdAllowedStatus.primStatus,
+ cmdAllowedStatus.secStatus);
+ }
+
+ l_rc = cmdAllowedStatus.secStatus;
+ break;
+ }
+ } while (false); // Inner do..while ends
+
+ SBE_GLOBAL->sbeIntrSource.setIntrSource(SBE_RX_ROUTINE, curInterface );
+
+ // 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 ( SBE_GLOBAL->sbeIntrSource.isSet(SBE_RX_ROUTINE, SBE_INTERFACE_FIFO) )
+ {
+ SBE_GLOBAL->sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER,
+ SBE_INTERFACE_FIFO);
+ }
+
+ if ( SBE_GLOBAL->sbeIntrSource.isSet(SBE_RX_ROUTINE,
+ SBE_INTERFACE_FIFO_RESET) )
+ {
+ SBE_GLOBAL->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(&SBE_GLOBAL->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) &&
+ (l_rc != SBE_SEC_BLACKLISTED_CHIPOP_ACCESS ))
+ {
+ // It's likely a code bug or PK failure,
+ // or any other PSU/FIFO access (scom) failure.
+
+ // Add Error trace, collect FFDC and
+ // continue wait for the next interrupt
+ SBE_ERROR(SBE_FUNC"Unexpected failure, "
+ "l_rcPk=[%d], SBE_GLOBAL->sbeSemCmdProcess.count=[%d], l_rc=[%d]",
+ l_rcPk, SBE_GLOBAL->sbeSemCmdProcess.count, l_rc);
+ pk_halt();
+ }
+ if ( SBE_INTERFACE_PSU == curInterface )
+ {
+ sbeHandlePsuResponse(l_rc);
+ SBE_GLOBAL->sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER,
+ SBE_INTERFACE_PSU);
+ pk_irq_enable(SBE_IRQ_HOST_PSU_INTR);
+ }
+ else if ( SBE_INTERFACE_FIFO == curInterface )
+ {
+ sbeHandleFifoResponse(l_rc);
+ SBE_GLOBAL->sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER,
+ SBE_INTERFACE_FIFO);
+ pk_irq_enable(SBE_IRQ_SBEFIFO_DATA);
+ pk_irq_enable(SBE_IRQ_SBEFIFO_RESET);
+ }
+ continue;
+ }
+
+ SBE_DEBUG(SBE_FUNC"Posted SBE_GLOBAL->sbeSemCmdProcess, "
+ "SBE_GLOBAL->sbeSemCmdProcess.count=[%d]", SBE_GLOBAL->sbeSemCmdProcess.count);
+
+ } while (true); // thread always exists
+ #undef SBE_FUNC
+}
diff --git a/src/sbefw/core/sbecmdregaccess.C b/src/sbefw/core/sbecmdregaccess.C
new file mode 100644
index 00000000..40d3537c
--- /dev/null
+++ b/src/sbefw/core/sbecmdregaccess.C
@@ -0,0 +1,281 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdregaccess.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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 &regReq)
+{
+ 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 *)&regReqMsg, 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;
+#ifdef SEEPROM_IMAGE
+ RamCore ramCore( plat_getTargetHandleByChipletNumber
+ <fapi2::TARGET_TYPE_CORE>(core),
+ regReqMsg.threadNr );
+#endif
+
+ SBE_EXEC_HWP_NOARG(fapiRc, ramCore.ram_setup)
+ if( fapiRc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" ram_setup failed. threadNr:0x%x"
+ "chipletId:0x%02x", (uint32_t)regReqMsg.threadNr, core);
+ respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ ffdc.setRc(fapiRc);
+ break;
+ }
+
+ fapi2::buffer<uint64_t> data64;
+ uint64_t respData = 0;
+ for( uint32_t regIdx = 0; regIdx < regReqMsg.numRegs; regIdx++ )
+ {
+ SBE_EXEC_HWP(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;
+ }
+ SBE_EXEC_HWP_NOARG(fapiRc, ramCore.ram_cleanup)
+ if( fapiRc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" ram_cleanup failed. threadNr:0x%x"
+ "chipletId:0x%02x", (uint32_t)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 *)&regReqMsg, 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",
+ (uint32_t)regReqMsg.threadNr,
+ (uint32_t)regReqMsg.regType,
+ (uint32_t)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;
+#ifdef SEEPROM_IMAGE
+ RamCore ramCore( plat_getTargetHandleByChipletNumber
+ <fapi2::TARGET_TYPE_CORE>(core),
+ regReqMsg.threadNr );
+#endif
+
+ SBE_EXEC_HWP_NOARG(fapiRc, ramCore.ram_setup)
+ if( fapiRc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" ram_setup failed. threadNr:0x%x"
+ "chipletId:0x%02x", (uint32_t)regReqMsg.threadNr, core);
+ respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ ffdc.setRc(fapiRc);
+ break;
+ }
+
+ fapi2::buffer<uint64_t> data64;
+ for( uint32_t regIdx = 0; regIdx < regReqMsg.numRegs; regIdx++ )
+ {
+ data64 = regPkg[regIdx].getData();
+ SBE_EXEC_HWP(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;
+ }
+ SBE_EXEC_HWP_NOARG(fapiRc, ramCore.ram_cleanup)
+ if( fapiRc )
+ {
+ SBE_ERROR(SBE_FUNC" ram_cleanup failed. threadNr:0x%x"
+ " chipletId:0x%02x",
+ (uint32_t)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/core/sbecmdregaccess.H b/src/sbefw/core/sbecmdregaccess.H
new file mode 100644
index 00000000..05c10d8d
--- /dev/null
+++ b/src/sbefw/core/sbecmdregaccess.H
@@ -0,0 +1,56 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdregaccess.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdregaccess.H
+ *
+ * @brief This file contains the Interfaces for the SCOM Access chip-ops
+ *
+ */
+
+#ifndef __SBEFW_SBECMDREGACCESS_H
+#define __SBEFW_SBECMDREGACCESS_H
+
+#include <stdint.h>
+
+/**
+ * @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/core/sbecmdringaccess.C b/src/sbefw/core/sbecmdringaccess.C
new file mode 100644
index 00000000..1db28734
--- /dev/null
+++ b/src/sbefw/core/sbecmdringaccess.C
@@ -0,0 +1,361 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdringaccess.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdringaccess.C
+ *
+ * @brief This file contains the SBE Ring Access chipOps
+ *
+ */
+
+#include "sbecmdringaccess.H"
+#include "sbefifo.H"
+#include "sbe_sp_intf.H"
+#include "sbetrace.H"
+#include "sbeHostMsg.H"
+#include "sbeHostUtils.H"
+#include "sbeFifoMsgUtils.H"
+#include "sbeutil.H"
+#include "sbefapiutil.H"
+#include "fapi2.H"
+#include "plat_hw_access.H"
+#include "sbeglobals.H"
+
+using namespace fapi2;
+
+static const uint32_t SIZE_OF_LENGTH_INWORDS = 1;
+static const uint32_t NUM_WORDS_PER_GRANULE = 2;
+static const uint32_t GETRING_GRANULE_SIZE_IN_BITS = 64;
+
+
+uint32_t sbePutRingFromImagePSU (uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbePutRingFromImagePSU "
+ SBE_ENTER(SBE_FUNC);
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t l_fapiRc = FAPI2_RC_SUCCESS;
+ sbePSUPutRingCMD_t l_cmd = {0};
+ do
+ {
+ // Fetch Ring ID, Ring mode and pervasive chiplet id from the message
+ // and also send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1
+ l_rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1,
+ (sizeof(l_cmd)/sizeof(uint64_t)),
+ (uint64_t*)&l_cmd,
+ true);
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_ERROR(SBE_FUNC "Failed to extract SBE_HOST_PSU_MBOX_REG1 and "
+ "SBE_HOST_PSU_MBOX_REG2");
+ break;
+ }
+
+ // Construct a Target from Chiplet ID and Target Type
+ fapi2::plat_target_handle_t l_tgtHndl;
+ if(!sbeGetFapiTargetHandle(l_cmd.TargetType, l_cmd.ChipletID,
+ l_tgtHndl))
+ {
+ SBE_ERROR(SBE_FUNC "Invalid target type [0x%04x]",
+ (uint16_t)l_cmd.TargetType);
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INVALID_DATA,
+ SBE_SEC_INVALID_TARGET_TYPE_PASSED);
+ break;
+ }
+ fapi2::Target<TARGET_TYPE_ALL> l_Tgt(l_tgtHndl);
+
+ // Initialize with HEADER CHECK mode
+ uint16_t l_ringMode = sbeToFapiRingMode(l_cmd.RingMode);
+
+ l_fapiRc = (uint32_t)putRing(l_Tgt, (RingID)l_cmd.RingID,
+ (RingMode)l_ringMode);
+ if(l_fapiRc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC "putRing HWP failure - "
+ "MSG - Target Type [0x%04x] Ring ID [0x%04x]"
+ " Ring Mode [0x%04x] Chiplet ID [0x%04x]",
+ l_cmd.TargetType,
+ l_cmd.RingID,
+ l_cmd.RingMode,
+ l_cmd.ChipletID);
+ break;
+ }
+ }while(0); // End of do-while
+
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, l_rc);
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+uint32_t sbeGetRing(uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbeGetRing "
+ SBE_ENTER(SBE_FUNC);
+
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ sbeGetRingAccessMsgHdr_t l_reqMsg;
+ sbeRespGenHdr_t respHdr;
+ respHdr.init();
+ sbeResponseFfdc_t l_ffdc;
+ ReturnCode l_fapiRc;
+ uint32_t l_len = 0;
+
+ //Note-Read operation flow is SHIFT and then READ.
+ // First time , the shift count will be 0.. because of the way it
+ // works. if we shift 64bits in the very first iteration then we
+ // loose first 64 bit. But still we should update l_bitSentCnt
+ // because we are sending back this data
+ uint32_t l_bitSentCnt = 64;
+ const uint32_t LONG_ROTATE_ADDRESS = 0x0003E000;
+
+ do
+ {
+ // Get the ring access header
+ l_len = sizeof(sbeGetRingAccessMsgHdr_t)/sizeof(uint32_t);
+ l_rc = sbeUpFifoDeq_mult (l_len, (uint32_t *)&l_reqMsg); // EOT fetch
+
+ // If FIFO access failure
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+
+ SBE_INFO(SBE_FUNC "Ring Address 0x%08X User Ring Mode 0x%04X "
+ "Length in Bits 0x%08X",
+ (uint32_t)l_reqMsg.ringAddr,
+ (uint32_t)l_reqMsg.ringMode,
+ (uint32_t)l_reqMsg.ringLenInBits);
+
+ uint16_t l_ringMode = sbeToFapiRingMode(l_reqMsg.ringMode);
+
+ // Call getRing_setup - loads the scan region data for the given ring
+ // address and updates the check word data
+ l_fapiRc = fapi2::getRing_setup(l_reqMsg.ringAddr,
+ (fapi2::RingMode)l_ringMode);
+ if( l_fapiRc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" getRing_setup failed. RingAddress:0x%08X "
+ "RingMode:0x%04x", l_reqMsg.ringAddr, l_ringMode);
+ respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ l_ffdc.setRc(l_fapiRc);
+ break;
+ }
+ // Calculate the iteration length
+ uint32_t l_loopCnt =
+ (l_reqMsg.ringLenInBits / GETRING_GRANULE_SIZE_IN_BITS);
+ // Check for modulus - remainder
+ uint8_t l_mod = (l_reqMsg.ringLenInBits % GETRING_GRANULE_SIZE_IN_BITS);
+ if(l_mod)
+ {
+ ++l_loopCnt;
+ }
+
+ // fix for the alignment issue
+ uint32_t l_buf[NUM_WORDS_PER_GRANULE]__attribute__ ((aligned (8))) ={0};
+ uint32_t l_bitShift = 0;
+ l_len = NUM_WORDS_PER_GRANULE;
+ plat_target_handle_t l_hndl;
+ uint32_t l_chipletId = (uint32_t)(l_reqMsg.ringAddr) & 0xFF000000;
+ uint32_t l_scomAddress = 0;
+
+ // Fetch the ring data in bits, each iteration will give you 64bits
+ for(uint32_t l_cnt=0; l_cnt < l_loopCnt; l_cnt++)
+ {
+
+ l_scomAddress = LONG_ROTATE_ADDRESS | l_chipletId;
+ l_scomAddress |= l_bitShift;
+ l_fapiRc = getscom_abs_wrap (&l_hndl,
+ l_scomAddress,
+ (uint64_t*)&l_buf);
+
+ if( l_fapiRc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" getRing_granule_data failed. "
+ "RingAddress:0x%08X RingMode:0x%04x",
+ l_reqMsg.ringAddr, l_ringMode);
+ respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ l_ffdc.setRc(l_fapiRc);
+ break;
+ }
+ // if the length of ring is not divisible by 64 then mod value
+ // should be considered which will match with the length in bits
+ // that passed
+ if((l_cnt == (l_loopCnt -1)) && (l_mod))
+ {
+ l_bitShift = l_mod;
+ }
+ // Send it to DS Fifo
+ // If this is the last iteration in the loop, let the full 64bit
+ // go, even for 1bit of remaining length. The length passed to
+ // the user will take care of actual number of bits.
+ l_rc = sbeDownFifoEnq_mult (l_len, (uint32_t *)&l_buf);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ l_bitSentCnt = l_bitSentCnt + l_bitShift;
+ l_bitShift = GETRING_GRANULE_SIZE_IN_BITS;
+ }
+ if ( (l_fapiRc == FAPI2_RC_SUCCESS) &&
+ (l_rc == SBE_SEC_OPERATION_SUCCESSFUL) )
+ {
+ if (!l_mod)
+ {
+ l_mod = GETRING_GRANULE_SIZE_IN_BITS;
+ }
+ //Here we need to shift with the mod value to enter into the
+ //starting position of the ring.But the data is already read in the
+ //above for loop.. so here we ignore the data
+ l_scomAddress = LONG_ROTATE_ADDRESS | l_chipletId;
+ l_scomAddress |= l_mod;
+ l_fapiRc = getscom_abs_wrap (&l_hndl,
+ l_scomAddress,
+ (uint64_t*)&l_buf);
+
+ if( l_fapiRc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" getRing_granule_data failed. "
+ "RingAddress:0x%08X RingMode:0x%04x",
+ l_reqMsg.ringAddr, l_ringMode);
+ respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ l_ffdc.setRc(l_fapiRc);
+ break;
+ }
+
+ // Call getRing_verifyAndcleanup - verify the check word data is
+ // matching or not and will clean up the scan region data
+ l_fapiRc = getRing_verifyAndcleanup((uint32_t)(l_reqMsg.ringAddr),
+ (fapi2::RingMode)l_ringMode);
+ if( l_fapiRc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" getRing_verifyAndcleanup failed. "
+ "RingAddress:0x%08X RingMode:0x%04x",
+ l_reqMsg.ringAddr, l_ringMode);
+ respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ l_ffdc.setRc(l_fapiRc);
+ }
+ }
+ }while(false);
+
+ // Now build and enqueue response into downstream FIFO
+ // If there was a FIFO error, will skip sending the response,
+ // instead give the control back to the command processor thread
+ if ( SBE_SEC_OPERATION_SUCCESSFUL == l_rc )
+ {
+ l_len = SIZE_OF_LENGTH_INWORDS;
+ l_rc = sbeDownFifoEnq_mult (l_len, &(l_bitSentCnt));
+ if(SBE_SEC_OPERATION_SUCCESSFUL == l_rc)
+ {
+ l_rc = sbeDsSendRespHdr( respHdr, &l_ffdc);
+ }
+ }
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+#undef SBE_FUNC
+}
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+uint32_t sbePutRing(uint8_t *i_pArg)
+{
+#define SBE_FUNC " sbePutRing "
+ SBE_ENTER(SBE_FUNC);
+
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ sbePutRingMsg_t reqMsg;
+ sbeRespGenHdr_t respHdr;
+ respHdr.init();
+ sbeResponseFfdc_t ffdc;
+ ReturnCode fapiRc;
+ sbePutRingMsgHdr_t hdr;
+ uint32_t len = 0;
+
+ do
+ {
+ // Get the length of payload
+ // Length is not part of chipop. So take length from total length
+ len = SBE_GLOBAL->sbeFifoCmdHdr.len -
+ sizeof(SBE_GLOBAL->sbeFifoCmdHdr)/sizeof(uint32_t);
+ uint32_t rs4FifoEntries = len -
+ sizeof(sbePutRingMsgHdr_t)/sizeof(uint32_t);
+
+ if( rs4FifoEntries > (SBE_PUT_RING_RS4_MAX_DOUBLE_WORDS * 2) )
+ {
+ SBE_ERROR(SBE_FUNC" RS4 palyload size is wrong."
+ "size(entries):0x%08x", rs4FifoEntries);
+ respHdr.setStatus( SBE_PRI_INVALID_DATA,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ // flush the fifo
+ rc = sbeUpFifoDeq_mult(len, NULL,true, true);
+ break;
+ }
+
+ len = sizeof(sbePutRingMsgHdr_t)/sizeof(uint32_t);
+ rc = sbeUpFifoDeq_mult (len, (uint32_t *)&hdr, false);
+ // If FIFO access failure
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(rc);
+
+ len = rs4FifoEntries;
+ rc = sbeUpFifoDeq_mult (len, (uint32_t *)&reqMsg);
+ // If FIFO access failure
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(rc);
+
+ uint16_t ringMode = sbeToFapiRingMode(hdr.ringMode);
+ bool i_applyOverride = false;
+
+ if (hdr.ringMode & SBE_RING_MODE_APPLY_OVERRIDE)
+ {
+ i_applyOverride = true;
+ }
+
+
+
+ Target<TARGET_TYPE_PROC_CHIP> proc = plat_getChipTarget();
+ // No need to pass length as platform api takes length from payload.
+ fapiRc = rs4DecompressionSvc(proc, (uint8_t *)reqMsg.rs4Payload,
+ i_applyOverride, (fapi2::RingMode)ringMode);
+ if( fapiRc != FAPI2_RC_SUCCESS )
+ {
+ SBE_ERROR(SBE_FUNC" rs4DecompressionSvc failed."
+ "RingMode:0x%04x", ringMode);
+ respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION);
+ ffdc.setRc(fapiRc);
+ break;
+ }
+ }while(false);
+
+ // Now build and enqueue response into downstream FIFO
+ // If there was a FIFO error, will skip sending the response,
+ // instead give the control back to the command processor thread
+ if ( SBE_SEC_OPERATION_SUCCESSFUL == rc )
+ {
+ rc = sbeDsSendRespHdr( respHdr, &ffdc);
+ }
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+#undef SBE_FUNC
+}
+
diff --git a/src/sbefw/core/sbecmdringaccess.H b/src/sbefw/core/sbecmdringaccess.H
new file mode 100644
index 00000000..54314c15
--- /dev/null
+++ b/src/sbefw/core/sbecmdringaccess.H
@@ -0,0 +1,71 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdringaccess.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdringaccess.H
+ *
+ * @brief This file contains the Interfaces for the RING Access chip-ops
+ *
+ */
+
+#ifndef __SBEFW_SBECMDRINGACCESS_H
+#define __SBEFW_SBECMDRINGACCESS_H
+
+#include <stdint.h>
+
+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);
+
+/**
+ * @brief Put Ring Command
+ *
+ * @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 sbePutRing(uint8_t *i_pArg);
+
+#endif /* __SBEFW_SBECMDRINGACCESS_H */
diff --git a/src/sbefw/core/sbecmdscomaccess.C b/src/sbefw/core/sbecmdscomaccess.C
new file mode 100644
index 00000000..f2b42608
--- /dev/null
+++ b/src/sbefw/core/sbecmdscomaccess.C
@@ -0,0 +1,432 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdscomaccess.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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"
+#include "plat_hw_access.H"
+#include "sbeglobals.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;
+ sbeRespGenHdr_t l_hdr;
+ l_hdr.init();
+ sbeResponseFfdc_t l_ffdc;
+
+ do
+ {
+ // 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_len2enqueue = 0;
+ uint32_t l_sbeDownFifoRespBuf[2] = {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);
+ checkIndirectAndDoScom(true, l_addr,
+ l_scomData, &l_hdr,
+ &l_ffdc);
+
+ if (l_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed
+ {
+ SBE_ERROR(SBE_FUNC"getscom failed, "
+ "scomAddr[0x%08X%08X]",
+ l_getScomReqMsg.hiAddr, l_getScomReqMsg.lowAddr);
+ break;
+ }
+ 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;
+ }
+ } // end successful scom
+
+ } while(false);
+
+ if(l_rc == SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ // Build the response header packet
+ l_rc = sbeDsSendRespHdr(l_hdr, &l_ffdc);
+ // will let command processor routine
+ // handle the failure
+ }
+
+ 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;
+ sbeRespGenHdr_t l_hdr;
+ l_hdr.init();
+ sbeResponseFfdc_t l_ffdc;
+
+ do
+ {
+ // 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;
+ // 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);
+ checkIndirectAndDoScom(false, l_addr,
+ l_scomData, &l_hdr, &l_ffdc);
+
+ if (l_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed
+ {
+ 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));
+ break;
+ }
+
+ } while(false);
+
+ if(l_rc == SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ // Build the response header packet
+ l_rc = sbeDsSendRespHdr(l_hdr, &l_ffdc);
+ // will let command processor routine
+ // handle the failure
+ }
+
+ 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;
+ sbeRespGenHdr_t l_hdr;
+ l_hdr.init();
+ sbeResponseFfdc_t l_ffdc;
+
+ do
+ {
+ // 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;
+ }
+
+ // 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_hdr.setStatus(SBE_PRI_INVALID_DATA,
+ 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);
+ checkIndirectAndDoScom(true, l_addr,
+ l_scomData, &l_hdr, &l_ffdc);
+
+ if (l_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed
+ {
+ SBE_ERROR(SBE_FUNC"getscom failed,"
+ " ScomAddress[0x%08X %08X]",
+ l_modifyScomMsg.hiAddr, l_modifyScomMsg.lowAddr);
+ 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
+ checkIndirectAndDoScom(false, l_addr,
+ l_modifyingData, &l_hdr, &l_ffdc);
+
+ if (l_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed
+ {
+ SBE_ERROR(SBE_FUNC"putscom failed,"
+ " ScomAddress[0x%08X%08X]",
+ l_modifyScomMsg.hiAddr, l_modifyScomMsg.lowAddr);
+ SBE_ERROR(SBE_FUNC"modifyingData[0x%08X%08X]",
+ SBE::higher32BWord(l_modifyingData),
+ SBE::lower32BWord(l_modifyingData));
+ break;
+ }
+ } while (false);
+
+ if(l_rc == SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ // Build the response header packet
+ l_rc = sbeDsSendRespHdr(l_hdr, &l_ffdc);
+ 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;
+ sbeRespGenHdr_t l_hdr;
+ l_hdr.init();
+ sbeResponseFfdc_t l_ffdc;
+
+ do
+ {
+ // 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;
+ }
+
+ 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;
+ checkIndirectAndDoScom(true, l_addr,
+ l_scomData, &l_hdr, &l_ffdc);
+
+ if (l_hdr.secondaryStatus == SBE_SEC_OPERATION_SUCCESSFUL) // scom success
+ {
+ l_putScomUmaskMsg.getScomData(l_scomData);
+
+ // Write the modified data
+ checkIndirectAndDoScom(false, l_addr,
+ l_scomData, &l_hdr, &l_ffdc);
+ }
+
+ if (l_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed
+ {
+ SBE_ERROR(SBE_FUNC"scom failed, "
+ "ScomAddress[0x%08X%08X]",
+ 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);
+
+ break;
+ }
+ } while (false);
+ } while(false);
+
+ if(l_rc == SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ // Build the response header packet
+ l_rc = sbeDsSendRespHdr(l_hdr, &l_ffdc);
+ // will let command processor routine
+ // handle the failure
+ }
+
+ 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/core/sbecmdscomaccess.H b/src/sbefw/core/sbecmdscomaccess.H
new file mode 100644
index 00000000..bd448053
--- /dev/null
+++ b/src/sbefw/core/sbecmdscomaccess.H
@@ -0,0 +1,93 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdscomaccess.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdscomaccess.H
+ *
+ * @brief This file contains the Interfaces for the SCOM Access chip-ops
+ *
+ */
+
+#ifndef __SBEFW_SBECMDSCOMACCESS_H
+#define __SBEFW_SBECMDSCOMACCESS_H
+
+#include <stdint.h>
+
+/**
+ * @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/core/sbecmdsram.C b/src/sbefw/core/sbecmdsram.C
new file mode 100644
index 00000000..ce05f7f6
--- /dev/null
+++ b/src/sbefw/core/sbecmdsram.C
@@ -0,0 +1,299 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdsram.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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 "sbeSecureMemRegionManager.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;
+
+#ifdef SEEPROM_IMAGE
+// Using Function pointer to force long call
+p9_pm_ocb_indir_setup_linear_FP_t p9_ocb_setup_linear_access_hwp = &p9_pm_ocb_indir_setup_linear;
+p9_pm_ocb_indir_access_FP_t p9_ocb_indirect_access_hwp = &p9_pm_ocb_indir_access;
+#endif
+
+///////////////////////////////////////////////////////////////////////
+// @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;
+
+ sbeRespGenHdr_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;
+ // Get the Req Struct Size Data from upstream Fifo
+ uint32_t l_len2dequeue = sizeof(l_req) / sizeof(uint32_t);
+
+ do
+ {
+ l_rc = sbeUpFifoDeq_mult (l_len2dequeue,
+ (uint32_t *)&l_req,
+ i_isGetFlag);
+
+
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ SBE_INFO("mode [0x%08X] addr[0x%08X] len[0x%08X]",
+ (uint32_t)l_req.mode,
+ (uint32_t)l_req.addr,
+ (uint32_t)l_req.len);
+
+ // Get the Proc Chip Target to be passed in to the procedure call
+ Target<fapi2::TARGET_TYPE_PROC_CHIP> 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.setStatus( SBE_PRI_INVALID_DATA, l_rc);
+ break;
+ }
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ // Check if the access to the address is allowed
+ if(l_validAddrForFirstAccess)
+ {
+ l_respHdr.secondaryStatus = occSramSecRegionManager.isAccessAllowed(
+ {static_cast<uint64_t>(l_req.addr)&(0x00000000FFFFFFFFull),
+ l_req.len,
+ (i_isGetFlag? static_cast<uint8_t>(memRegionMode::READ):
+ static_cast<uint8_t>(memRegionMode::WRITE))});
+ if(l_respHdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ l_respHdr.primaryStatus = SBE_PRI_UNSECURE_ACCESS_DENIED;
+ break;
+ }
+ }
+
+ // Setup Needs to be called in Normal and Debug Mode only
+ if( (l_req.mode == NORMAL_MODE) || (l_req.mode == DEBUG_MODE) )
+ {
+ SBE_EXEC_HWP(l_fapiRc, p9_ocb_setup_linear_access_hwp,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.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);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ }
+
+ // 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.
+ SBE_EXEC_HWP(l_fapiRc,
+ p9_ocb_indirect_access_hwp,
+ 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.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);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+
+ }
+ } // End of while Put/Get from Hwp
+ }while(0);
+
+ 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);
+ 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_respHdr.primaryStatus != SBE_PRI_OPERATION_SUCCESSFUL)
+ {
+ l_rc = sbeUpFifoDeq_mult(l_len2dequeue, NULL,
+ true, true);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ }
+ // 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);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ }
+ }
+
+ uint32_t l_len = 1;
+ // first enqueue the length of data actually written
+ l_rc = sbeDownFifoEnq_mult(l_len, (uint32_t *)(&l_totalReturnLen));
+
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ l_rc = sbeDsSendRespHdr( l_respHdr, &l_ffdc);
+ }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/core/sbecmdsram.H b/src/sbefw/core/sbecmdsram.H
new file mode 100644
index 00000000..3dd0977b
--- /dev/null
+++ b/src/sbefw/core/sbecmdsram.H
@@ -0,0 +1,64 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdsram.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdsram.H
+ *
+ * @brief This file contains the Interfaces for the Sram Access chip-ops
+ *
+ */
+
+#ifndef __SBEFW_SBECMDSRAM_H
+#define __SBEFW_SBECMDSRAM_H
+
+#include <stdint.h>
+
+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/core/sbecmdtracearray.C b/src/sbefw/core/sbecmdtracearray.C
new file mode 100644
index 00000000..89641d15
--- /dev/null
+++ b/src/sbefw/core/sbecmdtracearray.C
@@ -0,0 +1,156 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdtracearray.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdtracearray.C
+ *
+ * @brief This file contains the SBE Control Tracearray chipOp
+ *
+ */
+#include "sbecmdtracearray.H"
+#include "sbefifo.H"
+#include "sbe_sp_intf.H"
+#include "sbetrace.H"
+#include "sbeFifoMsgUtils.H"
+#include "sbeutil.H"
+#include "sbefapiutil.H"
+#include "fapi2.H"
+
+#include "p9_sbe_tracearray.H"
+
+using namespace fapi2;
+
+constexpr uint32_t SBE_TRACE_GRANULE_NUM_ROWS = 1;
+constexpr uint32_t SBE_TRACEARRAY_BYTES_PER_ROW =
+ (P9_TRACEARRAY_BITS_PER_ROW / 8);
+constexpr uint32_t SBE_TRACE_GRANULE_NUM_WORDS =
+ (SBE_TRACE_GRANULE_NUM_ROWS * SBE_TRACEARRAY_BYTES_PER_ROW) /
+ sizeof(uint32_t);
+
+#ifdef SEEPROM_IMAGE
+p9_sbe_tracearray_FP_t p9_sbe_tracearray_hwp = &p9_sbe_tracearray;
+#endif
+
+uint32_t sbeControlTraceArray(uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbeControlTraceArray"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+
+ sbeControlTraceArrayCMD_t l_req = {};
+ sbeRespGenHdr_t respHdr;
+ respHdr.init();
+ sbeResponseFfdc_t l_ffdc;
+ ReturnCode l_fapiRc;
+ uint32_t l_NumWordsRead = 0;
+ uint32_t l_len = 0;
+
+ do
+ {
+ l_len = sizeof(sbeControlTraceArrayCMD_t)/sizeof(uint32_t);
+ l_rc = sbeUpFifoDeq_mult (l_len, (uint32_t *)&l_req); //EOT fetch
+
+ // If FIFO access failure
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+
+ SBE_INFO(SBE_FUNC" targetType [0x%04X] chipletId [0x%02X]"
+ " traceArrayId [0x%04X] operation [0x%04X]",
+ l_req.targetType,
+ l_req.chipletId,
+ l_req.traceArrayId,
+ l_req.operation);
+
+ // Construct a Target from Chiplet ID and Target Type
+ fapi2::plat_target_handle_t l_tgtHndl;
+ if(!sbeGetFapiTargetHandle(l_req.targetType, l_req.chipletId,
+ l_tgtHndl))
+ {
+ SBE_ERROR(SBE_FUNC "Invalid target type [0x%04x]",
+ (uint16_t)l_req.targetType);
+ respHdr.setStatus(SBE_PRI_INVALID_DATA,
+ SBE_SEC_INVALID_TARGET_TYPE_PASSED);
+ break;
+ }
+ proc_gettracearray_args l_args = {};
+ // Fill trace array Id
+ l_args.trace_bus = (p9_tracearray_bus_id)l_req.traceArrayId;
+ // Fill control arguments
+ l_args.reset_post_dump = (l_req.operation & SBE_TA_RESET);
+ l_args.restart_post_dump = (l_req.operation & SBE_TA_RESTART);
+ l_args.stop_pre_dump = (l_req.operation & SBE_TA_STOP);
+ l_args.collect_dump = (l_req.operation & SBE_TA_COLLECT_DUMP);
+ l_args.ignore_mux_setting = (l_req.operation &
+ SBE_TA_IGNORE_MUX_SETTING);
+
+ uint64_t l_buffer[SBE_TRACE_GRANULE_NUM_WORDS/2] = {};
+ for(uint32_t l_cur_row = 0; l_cur_row < P9_TRACEARRAY_NUM_ROWS;
+ l_cur_row++)
+ {
+ SBE_EXEC_HWP(l_fapiRc, p9_sbe_tracearray_hwp,
+ l_tgtHndl,
+ l_args,
+ l_buffer,
+ l_cur_row,
+ SBE_TRACE_GRANULE_NUM_ROWS);
+ if(l_fapiRc != FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR("p9_sbe_tracearray failed");
+ // Respond with HWP FFDC
+ respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION );
+ l_ffdc.setRc(l_fapiRc);
+ break;
+ }
+
+ // If dump is not requested, break from the loop
+ if(!l_args.collect_dump)
+ break;
+
+ // Put the buffer onto Fifo
+ SBE_DEBUG(SBE_FUNC " sending row [%d]", l_cur_row);
+ l_len = SBE_TRACE_GRANULE_NUM_WORDS;
+ l_rc = sbeDownFifoEnq_mult (l_len,
+ reinterpret_cast<uint32_t *>(l_buffer));
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc);
+ l_NumWordsRead += SBE_TRACE_GRANULE_NUM_WORDS;
+ }
+
+ } 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 )
+ {
+ SBE_INFO(SBE_FUNC " l_NumWordsRead [%d]", l_NumWordsRead);
+ l_len = sizeof(l_NumWordsRead)/sizeof(uint32_t);
+ l_rc = sbeDownFifoEnq_mult (l_len, &l_NumWordsRead);
+ 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/core/sbecmdtracearray.H b/src/sbefw/core/sbecmdtracearray.H
new file mode 100644
index 00000000..af8362fd
--- /dev/null
+++ b/src/sbefw/core/sbecmdtracearray.H
@@ -0,0 +1,54 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdtracearray.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdtracearray.H
+ *
+ * @brief This file contains the Interfaces for the Tracearray Control chip-op
+ *
+ */
+
+#ifndef __SBEFW_SBECMDTRACEARRAY_H
+#define __SBEFW_SBECMDTRACEARRAY_H
+
+#include <stdint.h>
+
+typedef struct
+{
+ uint32_t targetType:16;
+ uint32_t reserved:8;
+ uint32_t chipletId:8;
+ uint32_t traceArrayId:16;
+ uint32_t operation:16;
+} sbeControlTraceArrayCMD_t;
+
+/**
+ * @brief Control Trace Array Command (0xA602)
+ *
+ * @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 sbeControlTraceArray(uint8_t *i_pArg);
+
+#endif //__SBEFW_SBECMDTRACEARRAY_H
diff --git a/src/sbefw/core/sbecorefiles.mk b/src/sbefw/core/sbecorefiles.mk
new file mode 100644
index 00000000..3cfe235f
--- /dev/null
+++ b/src/sbefw/core/sbecorefiles.mk
@@ -0,0 +1,60 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/sbefw/core/sbecorefiles.mk $
+#
+# OpenPOWER sbe Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2017
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+SBECORE-CPP-SOURCES = sbemain.C
+SBECORE-CPP-SOURCES += sbeirq.C
+SBECORE-CPP-SOURCES += sbecmdreceiver.C
+SBECORE-CPP-SOURCES += sbecmdprocessor.C
+SBECORE-CPP-SOURCES += sbecmdparser.C
+SBECORE-CPP-SOURCES += sbecmdscomaccess.C
+SBECORE-CPP-SOURCES += sbecmdiplcontrol.C
+SBECORE-CPP-SOURCES += pool.C
+SBECORE-CPP-SOURCES += sbecmdgeneric.C
+SBECORE-CPP-SOURCES += sbeFifoMsgUtils.C
+SBECORE-CPP-SOURCES += sbecmdmemaccess.C
+SBECORE-CPP-SOURCES += sbeHostUtils.C
+SBECORE-CPP-SOURCES += sbecmdcntrldmt.C
+SBECORE-CPP-SOURCES += sbecmdsram.C
+SBECORE-CPP-SOURCES += sberegaccess.C
+SBECORE-CPP-SOURCES += sbecmdcntlinst.C
+SBECORE-CPP-SOURCES += sbecmdregaccess.C
+SBECORE-CPP-SOURCES += sbeFFDC.C
+SBECORE-CPP-SOURCES += sbecmdringaccess.C
+SBECORE-CPP-SOURCES += sbescom.C
+SBECORE-CPP-SOURCES += sbecmdmpipl.C
+SBECORE-CPP-SOURCES += sbefapiutil.C
+SBECORE-CPP-SOURCES += sbeutil.C
+SBECORE-CPP-SOURCES += sbecmdtracearray.C
+SBECORE-CPP-SOURCES += sbeTimerSvc.C
+SBECORE-CPP-SOURCES += sbecmdCntrlTimer.C
+SBECORE-CPP-SOURCES += sbeHostMsg.C
+SBECORE-CPP-SOURCES += sbeSpMsg.C
+SBECORE-CPP-SOURCES += sbeglobals.C
+SBECORE-CPP-SOURCES += sbeMemAccessInterface.C
+SBECORE-CPP-SOURCES += sbeSecureMemRegionManager.C
+SBECORE-CPP-SOURCES += sbeSecurity.C
+
+SBECORE-C-SOURCES =
+SBECORE-S-SOURCES =
+
+SBECORE_OBJECTS = $(SBECORE-C-SOURCES:.c=.o) $(SBECORE-CPP-SOURCES:.C=.o) $(SBECORE-S-SOURCES:.S=.o)
diff --git a/src/sbefw/core/sbecoreseepromfiles.mk b/src/sbefw/core/sbecoreseepromfiles.mk
new file mode 100644
index 00000000..5c82f5a3
--- /dev/null
+++ b/src/sbefw/core/sbecoreseepromfiles.mk
@@ -0,0 +1,34 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/sbefw/core/sbecoreseepromfiles.mk $
+#
+# OpenPOWER sbe Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2017
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+SBECORESEEPROM-CPP-SOURCES = sbecmdgeneric.C
+SBECORESEEPROM-CPP-SOURCES += sbecmdmpipl.C
+SBECORESEEPROM-CPP-SOURCES += sbecmdmemaccess.C
+SBECORESEEPROM-CPP-SOURCES += sbeSecureMemRegionManager.C
+SBECORESEEPROM-CPP-SOURCES += sbecmdiplcontrol.C
+SBECORESEEPROM-CPP-SOURCES += sbecmdfastarray.C
+
+SBECORESEEPROM-C-SOURCES =
+SBECORESEEPROM-S-SOURCES =
+
+SBECORESEEPROM_OBJECTS = $(SBECORESEEPROM-C-SOURCES:.c=.o) $(SBECORESEEPROM-CPP-SOURCES:.C=.o) $(SBECORESEEPROM-S-SOURCES:.S=.o)
diff --git a/src/sbefw/core/sbeerrorcodes.H b/src/sbefw/core/sbeerrorcodes.H
new file mode 100644
index 00000000..01665ba8
--- /dev/null
+++ b/src/sbefw/core/sbeerrorcodes.H
@@ -0,0 +1,49 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeerrorcodes.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbeerrorcodes.H
+ *
+ * @brief This file contains the SBE internal error status codes
+ *
+ */
+
+#ifndef __SBEFW_SBEERRORCODES_H
+#define __SBEFW_SBEERRORCODES_H
+
+#include <stdint.h>
+
+
+/**
+ * @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/core/sbeevents.H b/src/sbefw/core/sbeevents.H
new file mode 100644
index 00000000..783dc183
--- /dev/null
+++ b/src/sbefw/core/sbeevents.H
@@ -0,0 +1,89 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeevents.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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_RUNTIME_EVENT = 0x0, // From Unknown/ISTEP/IPLING State
+ SBE_ISTEP_EVENT = 0x1, // From Unknown State
+ SBE_PLCK_EVENT = 0x2, // From Unknown state
+ SBE_DUMP_FAILURE_EVENT = 0x3, // From IPLING/RUNTIME/MPIPL/DMT/Unknown State
+ SBE_ENTER_MPIPL_EVENT = 0x4, // From Runtime State
+ SBE_CONTINUE_MPIPL_EVENT = 0x5, // From MPIPL Wait State
+ SBE_DMT_ENTER_EVENT = 0x6, // From Runtime State
+ SBE_DMT_COMP_EVENT = 0x7, // From DMT State
+ SBE_FAILURE_EVENT = 0x8, // From Any State
+ SBE_QUIESCE_EVENT = 0x9, // From Any State
+};
+
+// Maximum number of Events per State
+enum maxEventPerState
+{
+ SBE_STATE_UNKNOWN_MAX_EVENT = 4,
+ SBE_STATE_IPLING_MAX_EVENT = 4,
+ SBE_STATE_ISTEP_MAX_EVENT = 3,
+ SBE_STATE_MPIPL_MAX_EVENT = 3,
+ SBE_STATE_RUNTIME_MAX_EVENT = 5,
+ SBE_STATE_DMT_MAX_EVENT = 3,
+ SBE_STATE_DUMP_MAX_EVENT = 0,
+ SBE_STATE_FAILURE_MAX_EVENT = 0,
+ SBE_STATE_QUIESCE_MAX_EVENT = 0,
+
+ // Total number of State Transition Events, Addition of all the above
+ SBE_MAX_TRANSITIONS = 22,
+};
+
+
+// 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_IPLING_ENTRY_TO_MAP = SBE_STATE_UNKNOWN_ENTRY_TO_MAP + SBE_STATE_UNKNOWN_MAX_EVENT, // 4
+ SBE_STATE_ISTEP_ENTRY_TO_MAP = SBE_STATE_IPLING_ENTRY_TO_MAP + SBE_STATE_IPLING_MAX_EVENT, //8
+ SBE_STATE_MPIPL_ENTRY_TO_MAP = SBE_STATE_ISTEP_ENTRY_TO_MAP + SBE_STATE_ISTEP_MAX_EVENT, //11
+ SBE_STATE_RUNTIME_ENTRY_TO_MAP = SBE_STATE_MPIPL_ENTRY_TO_MAP + SBE_STATE_MPIPL_MAX_EVENT, //14
+ SBE_STATE_DMT_ENTRY_TO_MAP = SBE_STATE_RUNTIME_ENTRY_TO_MAP + SBE_STATE_RUNTIME_MAX_EVENT, //19
+ SBE_STATE_DUMP_ENTRY_TO_MAP = SBE_STATE_DMT_ENTRY_TO_MAP + SBE_STATE_DMT_MAX_EVENT, //22
+ SBE_STATE_FAILURE_ENTRY_TO_MAP = SBE_STATE_DUMP_ENTRY_TO_MAP + SBE_STATE_DUMP_MAX_EVENT, //22
+ SBE_STATE_QUIESCE_ENTRY_TO_MAP = SBE_STATE_FAILURE_ENTRY_TO_MAP + SBE_STATE_FAILURE_MAX_EVENT, //22
+};
+
+#endif //__SBEFW_SBEEVENTS_H
+
diff --git a/src/sbefw/core/sbeexeintf.H b/src/sbefw/core/sbeexeintf.H
new file mode 100644
index 00000000..80d89586
--- /dev/null
+++ b/src/sbefw/core/sbeexeintf.H
@@ -0,0 +1,235 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeexeintf.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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 = 512,
+ SBE_THREAD_ASYNC_CMD_PROC_STACK_SIZE = 256,
+ SBE_THREAD_CMD_RECV_STACK_SIZE = 512,
+ SBE_THREAD_SYNC_CMD_PROC_STACK_SIZE = 2048,
+};
+
+/**
+ * @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;
+
+/**
+ * @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/core/sbefapiutil.C b/src/sbefw/core/sbefapiutil.C
new file mode 100644
index 00000000..b7cabc29
--- /dev/null
+++ b/src/sbefw/core/sbefapiutil.C
@@ -0,0 +1,150 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbefapiutil.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/src/sbefw/sbefapiutil.C
+ *
+ * @brief This file contains the SBE FAPI Utility
+ *
+ */
+
+#include "sbefapiutil.H"
+
+using namespace fapi2;
+
+fapi2::TargetType sbeGetFapiTargetType(const uint16_t i_sbeTargetType,
+ const uint16_t i_chipletId)
+{
+ TargetType l_fapiTargetType = TARGET_TYPE_NONE;
+ switch(i_sbeTargetType)
+ {
+ case TARGET_EX:
+ if((i_chipletId >= SMT4_CORE0_ID) &&
+ (i_chipletId <= SMT4_CORE_ID_LAST))
+ {
+ l_fapiTargetType = fapi2::TARGET_TYPE_EX;
+ }
+ break;
+ case TARGET_PERV:
+ if((i_chipletId >= EQ_ID_0) && (i_chipletId <= EQ_ID_LAST))
+ {
+ l_fapiTargetType = fapi2::TARGET_TYPE_EQ;
+ }
+ else if((i_chipletId >= SMT4_CORE0_ID) &&
+ (i_chipletId <= SMT4_CORE_ID_LAST))
+ {
+ l_fapiTargetType = fapi2::TARGET_TYPE_CORE;
+ }
+ else
+ {
+ l_fapiTargetType = fapi2::TARGET_TYPE_PERV;
+ }
+ break;
+ case TARGET_PROC_CHIP:
+ l_fapiTargetType = fapi2::TARGET_TYPE_PROC_CHIP;
+ break;
+ }
+ return l_fapiTargetType;
+}
+
+bool sbeGetFapiTargetHandle(const uint16_t i_targetType,
+ const uint16_t i_chipletId,
+ fapi2::plat_target_handle_t &o_tgtHndl,
+ const fapi2::TargetType i_fapiTargetMask)
+{
+ bool l_rc = true;
+
+ do
+ {
+ if(((i_targetType == TARGET_TYPE_CORE) &&
+ (i_chipletId == SMT4_ALL_CORES)) ||
+ ((i_targetType == TARGET_TYPE_EQ) &&
+ (i_chipletId == EQ_ALL_CHIPLETS)))
+ {
+ // It's a valid combination for all cores/all EQs
+ break;
+ }
+ fapi2::TargetType l_fapiTargetType = static_cast<TargetType>(
+ sbeGetFapiTargetType(i_targetType, i_chipletId)
+ & i_fapiTargetMask);
+ switch(l_fapiTargetType)
+ {
+ case fapi2::TARGET_TYPE_EX:
+ o_tgtHndl = plat_getTargetHandleByChipletNumber
+ <fapi2::TARGET_TYPE_EX>(i_chipletId);
+ break;
+ case fapi2::TARGET_TYPE_PERV:
+ o_tgtHndl = plat_getTargetHandleByChipletNumber
+ <fapi2::TARGET_TYPE_PERV>(i_chipletId);
+ break;
+ case fapi2::TARGET_TYPE_EQ:
+ o_tgtHndl = plat_getTargetHandleByChipletNumber
+ <fapi2::TARGET_TYPE_EQ>(i_chipletId);
+ break;
+ case fapi2::TARGET_TYPE_CORE:
+ o_tgtHndl = plat_getTargetHandleByChipletNumber
+ <fapi2::TARGET_TYPE_CORE>(i_chipletId);
+ break;
+ case fapi2::TARGET_TYPE_PROC_CHIP:
+ o_tgtHndl = plat_getChipTarget().get();
+ break;
+ default:
+ l_rc = false;
+ break;
+ }
+ } while(false);
+ return l_rc;
+}
+
+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;
+ }
+ if(i_ringMode & SBE_RING_MODE_FASTARRAY)
+ {
+ l_fapiRingMode |= RING_MODE_FASTARRAY;
+ }
+ return l_fapiRingMode;
+}
+
+
diff --git a/src/sbefw/core/sbefapiutil.H b/src/sbefw/core/sbefapiutil.H
new file mode 100644
index 00000000..c2e72387
--- /dev/null
+++ b/src/sbefw/core/sbefapiutil.H
@@ -0,0 +1,76 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbefapiutil.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/src/sbefw/sbefapiutil.H
+ *
+ * @brief This file contains the SBE FAPI Utility
+ *
+ */
+
+#ifndef __SBEFW_SBEFAPIUTIL_H
+#define __SBEFW_SBEFAPIUTIL_H
+
+#include <stdint.h>
+#include "sbe_sp_intf.H"
+#include "sbeutil.H"
+#include "fapi2.H"
+#include "plat_hw_access.H"
+
+/* @brief - Map SBE target Types to Fapi Target Types
+ *
+ * @param[in] - i_sbeTargetType SBE target type
+ * @param[in] - i_chipletId Chiplet Id
+ *
+ * @return - fapi target type
+ */
+fapi2::TargetType sbeGetFapiTargetType(const uint16_t i_sbeTargetType,
+ const uint16_t i_chipletId);
+
+/*@brief - create fapi target handle for the target type
+ *
+ * @param[in] - i_taretType - sbe target type
+ * @param[in] - i_chipletId - chiplet id
+ * @param[out] - o_tgtHndl - fapi target handle
+ * @param[in] - i_fapiTargetMask - expected fapi targets, by default
+ * no masking
+ *
+ * @return - true - on success
+ * false - on failure
+ */
+bool sbeGetFapiTargetHandle(const uint16_t i_targetType,
+ const uint16_t i_chipletId,
+ fapi2::plat_target_handle_t &o_tgtHndl,
+ const fapi2::TargetType i_fapiTargetMask =
+ fapi2::TARGET_TYPE_ALL);
+
+/*@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);
+
+
+#endif /* __SBEFW_SBEFAPIUTIL_H */
diff --git a/src/sbefw/core/sbefifo.H b/src/sbefw/core/sbefifo.H
new file mode 100644
index 00000000..20385e26
--- /dev/null
+++ b/src/sbefw/core/sbefifo.H
@@ -0,0 +1,231 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbefifo.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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
+ union
+ {
+ sbe_upfifo_status_t statusOrReserved;
+ uint32_t status;
+ };
+} 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/core/sbeglobals.C b/src/sbefw/core/sbeglobals.C
new file mode 100644
index 00000000..8d9ef020
--- /dev/null
+++ b/src/sbefw/core/sbeglobals.C
@@ -0,0 +1,48 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeglobals.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "sbetrace.H"
+#include "sbeglobals.H"
+#include "sbe_build_info.H"
+////////////////////////////////////////////////////////////////
+//// @brief Stacks for Non-critical Interrupts and Threads
+//////////////////////////////////////////////////////////////////
+// Moved it out-side the scope of Global Class for symbol generation in syms
+uint8_t sbe_Kernel_NCInt_stack[SBE_NONCRITICAL_STACK_SIZE];
+uint8_t sbeCommandReceiver_stack[SBE_THREAD_CMD_RECV_STACK_SIZE];
+uint8_t sbeSyncCommandProcessor_stack[SBE_THREAD_SYNC_CMD_PROC_STACK_SIZE];
+uint8_t sbeAsyncCommandProcessor_stack[SBE_THREAD_ASYNC_CMD_PROC_STACK_SIZE];
+
+SBEGlobalsSingleton* sbeGlobal = &SBEGlobalsSingleton::getInstance();
+SBEGlobalsSingleton& SBEGlobalsSingleton::getInstance()
+{
+ static SBEGlobalsSingleton iv_instance;
+ return iv_instance;
+}
+// SBE commit id
+uint32_t SBEGlobalsSingleton::fwCommitId = SBE_COMMIT_ID;
+
+secureMemRegion_t SBEGlobalsSingleton::mainMemRegions[MAX_MAIN_STORE_REGIONS] = {};
+secureMemRegion_t SBEGlobalsSingleton::occSramRegions[MAX_OCC_SRAM_REGIONS] = {};
+
+uint64_t SBEGlobalsSingleton::i2cModeRegister = 0x004D000000000000ull;
diff --git a/src/sbefw/core/sbeglobals.H b/src/sbefw/core/sbeglobals.H
new file mode 100644
index 00000000..c26967a6
--- /dev/null
+++ b/src/sbefw/core/sbeglobals.H
@@ -0,0 +1,138 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeglobals.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __SBE_GLOBALS_H
+#define __SBE_GLOBALS_H
+
+#include "sbeutil.H"
+#include "sbeSpMsg.H"
+#include "sbeHostMsg.H"
+#include "sbestates.H"
+#include "sbeexeintf.H"
+#include "sbecmdgeneric.H"
+#include "sbeSecureMemRegionManager.H"
+
+#define SBE_GLOBAL sbeGlobal
+
+constexpr size_t MAX_MAIN_STORE_REGIONS = 8;
+constexpr size_t MAX_OCC_SRAM_REGIONS = 2;
+
+// Extern declartion, Defined in sbeglobal.C
+extern uint8_t sbe_Kernel_NCInt_stack[SBE_NONCRITICAL_STACK_SIZE];
+extern uint8_t sbeCommandReceiver_stack[SBE_THREAD_CMD_RECV_STACK_SIZE];
+extern uint8_t sbeSyncCommandProcessor_stack[SBE_THREAD_SYNC_CMD_PROC_STACK_SIZE];
+extern uint8_t sbeAsyncCommandProcessor_stack[SBE_THREAD_ASYNC_CMD_PROC_STACK_SIZE];
+
+class SBEGlobalsSingleton
+{
+ public:
+ // Disable copy contructor and assingment operator
+ SBEGlobalsSingleton(const SBEGlobalsSingleton&) = delete;
+ SBEGlobalsSingleton& operator=(const SBEGlobalsSingleton&) = delete;
+ static SBEGlobalsSingleton& getInstance();
+
+ sbeFifoCmdReqBuf_t sbeFifoCmdHdr;
+ sbeCmdRespHdr_t sbeCmdRespHdr;
+ sbePsu2SbeCmdReqHdr_t sbePsu2SbeCmdReqHdr;
+ sbeSbe2PsuRespHdr_t sbeSbe2PsuRespHdr;
+ sbeIntrHandle_t sbeIntrSource;
+ ////////////////////////////////////////////////////////////////
+ //// @brief Global semaphores
+ /////////////////////////////////////////////////////////////////
+ /**
+ * @brief Global semaphore : SBE_GLOBAL->sbeSemCmdRecv
+ *
+ * This is used to synchronize between the ISR and
+ * the command receiver thread.
+ *
+ */
+ PkSemaphore sbeSemCmdRecv;
+ /**
+ * @brief Global semaphore : SBE_GLOBAL->sbeSemCmdProcess
+ *
+ * This is used to synchronize between command receiver thread
+ * and synchronous command processor thread.
+ *
+ */
+ PkSemaphore sbeSemCmdProcess;
+ sbeRole SBERole;
+ // SBE Frequency. Initially nest frequency is 133 MHZ
+ uint32_t sbefreq;
+ // Host specified memory allocations
+ // passthrough command address
+ sbeHostAddr_t hostPassThroughCmdAddr;
+ // ffdc address
+ sbeHostAddr_t hostFFDCAddr;
+ // Key Addr Pair
+ sbeStashMemoryPair_t sbeKeyAddrPair;
+ // SBE FW security enabled; 0 - disabled; 1 - enabled
+ uint8_t sbeFWSecurityEnabled;
+ // Instance of Master EX core to be used for DMT FFDC collection
+ uint8_t deadmanCore;
+ // Cached HWP Return Code that hints at what HWP FFDC to collect
+ uint32_t asyncFfdcRC;
+
+ // SBE commit id
+ static uint32_t fwCommitId;
+
+ // Secure memory window arrays
+ static secureMemRegion_t mainMemRegions[MAX_MAIN_STORE_REGIONS];
+ static secureMemRegion_t occSramRegions[MAX_OCC_SRAM_REGIONS];
+
+ // i2c mode register register
+ static uint64_t i2cModeRegister;
+
+ ////////////////////////////////////////////////////////////////
+ //// @brief PkThread structure for SBE Command Receiver thread
+ //////////////////////////////////////////////////////////////////
+ PkThread sbeCommandReceiver_thread;
+ ////////////////////////////////////////////////////////////////
+ //// @brief PkThread structure for SBE Synchronous ChipOps
+ //// processing thread
+ //////////////////////////////////////////////////////////////////
+ PkThread sbeSyncCommandProcessor_thread;
+ ////////////////////////////////////////////////////////////////
+ ////// @brief PkThread structure for SBE Asynchronous ChipOps
+ ////// processing thread
+ //////////////////////////////////////////////////////////////////
+ PkThread sbeAsyncCommandProcessor_thread;
+ private:
+ /* Constructor
+ */
+ SBEGlobalsSingleton():
+ sbeFifoCmdHdr(),
+ sbeCmdRespHdr(),
+ sbePsu2SbeCmdReqHdr(),
+ sbeSbe2PsuRespHdr(),
+ sbeIntrSource(),
+ sbeSemCmdRecv(),
+ sbeSemCmdProcess(),
+ SBERole(SBE_ROLE_MASTER),
+ sbefreq(( 133 * 1000 * 1000)/SBE::SBE_TO_NEST_FREQ_FACTOR),
+ sbeFWSecurityEnabled(1)
+ {
+ }
+};
+extern SBEGlobalsSingleton* sbeGlobal;
+#endif //__SBE_GLOBALS_H
+
diff --git a/src/sbefw/core/sbeirq.C b/src/sbefw/core/sbeirq.C
new file mode 100644
index 00000000..9db6809c
--- /dev/null
+++ b/src/sbefw/core/sbeirq.C
@@ -0,0 +1,316 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeirq.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbeirq.C
+ *
+ * @brief This sets up and registers SBE ISRs
+ *
+ */
+
+#include "sbeexeintf.H"
+#include "sbeirq.H"
+#include "sbetrace.H"
+#include "assert.h"
+#include "sbeglobals.H"
+#include "ppe42_scom.h"
+#include "p9_misc_scom_addresses.H"
+
+////////////////////////////////////////////////////////////////
+// @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:
+ SBE_GLOBAL->sbeIntrSource.setIntrSource(SBE_INTERRUPT_ROUTINE,
+ SBE_INTERFACE_PSU);
+ break;
+
+ case SBE_IRQ_SBEFIFO_DATA:
+ SBE_GLOBAL->sbeIntrSource.setIntrSource(SBE_INTERRUPT_ROUTINE,
+ SBE_INTERFACE_FIFO);
+ pk_irq_disable(SBE_IRQ_SBEFIFO_RESET);
+ break;
+
+ case SBE_IRQ_SBEFIFO_RESET:
+ SBE_GLOBAL->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(&SBE_GLOBAL->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 I2C reset sequence
+uint32_t __max_i2c_reset_retrials = 3;
+
+// bit 0
+#define I2CM_RESET_BIT (0x8000000000000000ull)
+// bit 7
+#define I2C_CMD_COMPLETE_BIT (0x0100000000000000ull)
+// bit 3
+#define I2C_STOP_BIT (0x1000000000000000ull)
+// bit 16-21
+#define I2C_MODE_REG_PORT_BITS (0xFFFF03FFFFFFFFFFull)
+// bit 8
+#define I2C_MODE_FGAT_BIT (0x8000000000000000ull)
+
+#define POLL_BEFORE_I2C_RESET (25600)
+#define I2C_CMD_COMPLETE_POLL (0x00003FFF)
+
+extern "C" void i2c_reset()
+{
+ // empty cycles before i2c reset
+ for (auto i = POLL_BEFORE_I2C_RESET; i > 0; --i) {
+ // Force compiler not to optimize for loop
+ asm("");
+ }
+
+ uint32_t reg_address = 0;
+ uint64_t value = 0ull;
+
+ // reset I2CM register - 0x000A0001
+ reg_address = PU_RESET_REGISTER_B;
+ value = I2CM_RESET_BIT;
+ PPE_STVD( reg_address, value);
+
+ // forcefully reset port busy register - 0x000A000E
+ reg_address = PU_I2C_BUSY_REGISTER_B;
+ value = I2CM_RESET_BIT;
+ PPE_STVD( reg_address, value);
+
+ // clear bit 16-21 of mode register
+ SBE_GLOBAL->i2cModeRegister &= I2C_MODE_REG_PORT_BITS;
+ // set enchanced mode - fgat bit - 28
+ SBE_GLOBAL->i2cModeRegister |= I2C_MODE_FGAT_BIT;
+
+ for( auto port=0; port < 2; port++ )
+ {
+ // write mode register - 0x000A0006
+ reg_address = PU_MODE_REGISTER_B;
+ SBE_GLOBAL->i2cModeRegister |= ((uint64_t)port << 42);
+ PPE_STVD( reg_address, SBE_GLOBAL->i2cModeRegister );
+
+ // write command control register - 0x000A0005
+ reg_address = PU_COMMAND_REGISTER_B;
+ value = I2C_STOP_BIT;
+ PPE_STVD( reg_address, value );
+
+ // poll cmd complete register 0x000A000B
+ uint64_t status = 0;
+ for( auto i=0; i < I2C_CMD_COMPLETE_POLL; i--)
+ {
+ reg_address = PU_IMM_RESET_I2C_B;
+ PPE_LVD( reg_address, status );
+ if( status & I2C_CMD_COMPLETE_BIT )
+ {
+ // cmd complete
+ break;
+ }
+ }
+ if(!( status & I2C_CMD_COMPLETE_BIT ))
+ {
+ pk_halt();
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////
+// 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(
+ "# reclaim function callstack\n"
+ "lwz %r0,12(%r1)\n"
+ "mtlr %r0\n"
+ "addi %r1,%r1,8\n"
+
+ "# Save r0, r1, r2, r3,r4, r5, r6, r7, r8, r9, r10, r13, r28, r29, r30, r31\n"
+ "# lr to stack, since it is going to be used by\n"
+ "# this handler\n"
+ "stwu %r1, -68(%r1)\n"
+ "stw %r0, 0(%r1)\n"
+ "stw %r2, 4(%r1)\n"
+ "stw %r3, 8(%r1)\n"
+ "stw %r4, 12(%r1)\n"
+ "stw %r5, 16(%r1)\n"
+ "stw %r6, 20(%r1)\n"
+ "stw %r7, 24(%r1)\n"
+ "stw %r8, 28(%r1)\n"
+ "stw %r9, 32(%r1)\n"
+ "stw %r10, 36(%r1)\n"
+ "stw %r13, 40(%r1)\n"
+ "stw %r28, 44(%r1)\n"
+ "stw %r29, 48(%r1)\n"
+ "stw %r30, 52(%r1)\n"
+ "stw %r31, 56(%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, __halt_sbe\n"
+ "cmpwibgt %r4, 0x0003, __halt_sbe\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, halt the SBE\n"
+ "__halt_sbe:\n"
+ "b pk_halt\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"
+ "b __exit\n"
+ "__sbe_i2c_reset_sequence:\n"
+ "mflr %r0\n"
+ "stw %r0, 60(%r1)\n");
+ i2c_reset();
+ asm(
+ "lwz %r0, 60(%r1)\n"
+ "mtlr %r0\n"
+ "stw %r10, __max_i2c_reset_retrials@sda21(0)\n"
+ "__exit:\n"
+ "lwz %r0, 0(%r1)\n"
+ "lwz %r2, 4(%r1)\n"
+ "lwz %r3, 8(%r1)\n"
+ "lwz %r4, 12(%r1)\n"
+ "lwz %r5, 16(%r1)\n"
+ "lwz %r6, 20(%r1)\n"
+ "lwz %r7, 24(%r1)\n"
+ "lwz %r8, 28(%r1)\n"
+ "lwz %r9, 32(%r1)\n"
+ "lwz %r10, 36(%r1)\n"
+ "lwz %r13, 40(%r1)\n"
+ "lwz %r28, 44(%r1)\n"
+ "lwz %r29, 48(%r1)\n"
+ "lwz %r30, 52(%r1)\n"
+ "lwz %r31, 56(%r1)\n"
+ "addi %r1, %r1, 68\n"
+
+ "rfi\n"
+ );
+}
+
diff --git a/src/sbefw/core/sbeirq.H b/src/sbefw/core/sbeirq.H
new file mode 100644
index 00000000..5700cc9d
--- /dev/null
+++ b/src/sbefw/core/sbeirq.H
@@ -0,0 +1,109 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeirq.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * $file: ppe/sbe/sbefw/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/core/sbemain.C b/src/sbefw/core/sbemain.C
new file mode 100644
index 00000000..e49fc029
--- /dev/null
+++ b/src/sbefw/core/sbemain.C
@@ -0,0 +1,341 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbemain.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+/* @file: ppe/sbe/sbefw/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
+#include "sbeutil.H" // For getting SBE_TO_NEST_FREQ_FACTOR
+#include "sbeglobals.H"
+#include "p9_misc_scom_addresses.H"
+
+// Max defines for Semaphores
+static uint32_t MAX_SEMAPHORE_COUNT = 3;
+
+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(&SBE_GLOBAL->sbeSemCmdRecv, 0, MAX_SEMAPHORE_COUNT);
+ if (l_rc)
+ {
+ break;
+ }
+ l_rc = pk_semaphore_create(&SBE_GLOBAL->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(&SBE_GLOBAL->sbeCommandReceiver_thread,
+ sbeCommandReceiver_routine,
+ (void *)0,
+ (PkAddress)sbeCommandReceiver_stack,
+ SBE_THREAD_CMD_RECV_STACK_SIZE,
+ THREAD_PRIORITY_5);
+ if (l_rc)
+ {
+ break;
+ }
+
+ // Initialize Synchronous Command Processor thread
+ l_rc = createAndResumeThreadHelper(&SBE_GLOBAL->sbeSyncCommandProcessor_thread,
+ sbeSyncCommandProcessor_routine,
+ (void *)0,
+ (PkAddress)sbeSyncCommandProcessor_stack,
+ SBE_THREAD_SYNC_CMD_PROC_STACK_SIZE,
+ THREAD_PRIORITY_7);
+ if (l_rc)
+ {
+ break;
+ }
+
+ // Initialize Asynchronous Command Processor thread
+ l_rc = createAndResumeThreadHelper(&SBE_GLOBAL->sbeAsyncCommandProcessor_thread,
+ sbeAsyncCommandProcessor_routine,
+ (void *)0,
+ (PkAddress)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;
+
+ // backup i2c mode register
+ uint32_t reg_address = PU_MODE_REGISTER_B;
+ PPE_LVD( reg_address, SBE_GLOBAL->i2cModeRegister);
+
+ // @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)sbe_Kernel_NCInt_stack,
+ SBE_NONCRITICAL_STACK_SIZE,
+ 0,
+ SBE_GLOBAL->sbefreq );
+ 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;
+ }
+
+ fapiRc = fapi2::plat_AttrInit();
+ if(fapiRc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ SBE_ERROR(SBE_FUNC"plat_AttrInit 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;
+ }
+
+ if(SBE::isSimicsRunning())
+ {
+ SBE_INFO("SBE is running on simics");
+ }
+ // 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/core/sberegaccess.C b/src/sbefw/core/sberegaccess.C
new file mode 100644
index 00000000..03ffd852
--- /dev/null
+++ b/src/sbefw/core/sberegaccess.C
@@ -0,0 +1,356 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sberegaccess.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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 <ppe42_scom.h>
+#include <p9_perv_scom_addresses.H>
+#include <p9_misc_scom_addresses.H>
+
+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_IPLING_ENTRY_TO_MAP, SBE_STATE_IPLING_MAX_EVENT},
+ {SBE_STATE_ISTEP_ENTRY_TO_MAP, SBE_STATE_ISTEP_MAX_EVENT},
+ {SBE_STATE_MPIPL_ENTRY_TO_MAP, SBE_STATE_MPIPL_MAX_EVENT},
+ {SBE_STATE_RUNTIME_ENTRY_TO_MAP, SBE_STATE_RUNTIME_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},
+};
+
+// 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_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_QUIESCE_EVENT, SBE_STATE_QUIESCE},
+ {SBE_STATE_ISTEP, SBE_RUNTIME_EVENT, SBE_STATE_RUNTIME},
+ {SBE_STATE_ISTEP, SBE_FAILURE_EVENT, SBE_STATE_FAILURE},
+ {SBE_STATE_ISTEP, SBE_QUIESCE_EVENT, SBE_STATE_QUIESCE},
+ {SBE_STATE_MPIPL, SBE_RUNTIME_EVENT, SBE_STATE_RUNTIME},
+ {SBE_STATE_MPIPL, SBE_DUMP_FAILURE_EVENT, SBE_STATE_DUMP},
+ {SBE_STATE_MPIPL, SBE_QUIESCE_EVENT, SBE_STATE_QUIESCE},
+ {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_RUNTIME, SBE_QUIESCE_EVENT, SBE_STATE_QUIESCE},
+ {SBE_STATE_DMT, SBE_DMT_COMP_EVENT, SBE_STATE_RUNTIME},
+ {SBE_STATE_DMT, SBE_QUIESCE_EVENT, SBE_STATE_QUIESCE},
+ {SBE_STATE_DMT, SBE_DUMP_FAILURE_EVENT, SBE_STATE_DUMP},
+};
+
+SbeRegAccess SbeRegAccess::cv_instance __attribute__((section (".sbss")));
+
+/**
+ * @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 rc = 0;
+ uint64_t l_mbx8 = 0;
+ do
+ {
+ if(l_initDone)
+ {
+ break;
+ }
+ // Read SBE messaging register into iv_messagingReg
+ rc = getscom_abs(PERV_SB_MSG_SCOM, &iv_messagingReg);
+ if(PCB_ERROR_NONE != rc)
+ {
+ SBE_ERROR(SBE_FUNC"Failed reading sbe messaging reg., RC: 0x%08X. ",
+ rc);
+ break;
+ }
+ // Read Mailbox register 8 to check if the mailbox registers 3 and 6 are
+ // valid
+ rc = getscom_abs(PERV_SCRATCH_REGISTER_8_SCOM, &l_mbx8);
+ if(PCB_ERROR_NONE != rc)
+ {
+ SBE_ERROR(SBE_FUNC"Failed reading mailbox reg 7, RC: 0x%08X. ",
+ rc);
+ break;
+ }
+ if(l_mbx8 & SBE_MBX8_MBX3_VALID_MASK)
+ {
+ // Read MBX3
+ rc = getscom_abs(PERV_SCRATCH_REGISTER_3_SCOM, &iv_mbx3);
+ if(PCB_ERROR_NONE != rc)
+ {
+ SBE_ERROR(SBE_FUNC"Failed reading mailbox reg 3, RC: 0x%08X. ",
+ rc);
+ break;
+ }
+ }
+ else
+ {
+ // Need to read the values off the attributes
+ uint32_t l_attr = 0;
+ FAPI_ATTR_GET(ATTR_BOOT_FLAGS, Target<TARGET_TYPE_SYSTEM>(),
+ l_attr);
+ iv_mbx3 = ((uint64_t) l_attr ) << 32;
+ }
+ if(l_mbx8 & SBE_MBX8_MBX6_VALID_MASK)
+ {
+ // Read MBX6
+ rc = getscom_abs(PERV_SCRATCH_REGISTER_6_SCOM, &iv_mbx6);
+ if(PCB_ERROR_NONE != rc)
+ {
+ SBE_ERROR(SBE_FUNC"Failed reading mailbox reg 6, RC: 0x%08X. "
+ rc);
+ break;
+ }
+ }
+
+ // If the master/slave bit is 0 (either default or read from mbx6),
+ // check the C4 board pin to determine role
+ // Read device ID register
+ uint64_t l_sbeDevIdReg = 0;
+ rc = getscom_abs(PERV_DEVICE_ID_REG, &l_sbeDevIdReg);
+ if(PCB_ERROR_NONE != rc)
+ {
+ SBE_ERROR(SBE_FUNC"Failed reading device id reg, RC: 0x%08X.",rc);
+ break;
+ }
+
+ if(0 == iv_isSlave)
+ {
+ 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 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 rc = 0;
+
+ iv_prevState = iv_currState;
+ iv_currState = i_state;
+ rc = putscom_abs(PERV_SB_MSG_SCOM, iv_messagingReg);
+ if(PCB_ERROR_NONE != rc)
+ {
+ SBE_ERROR(SBE_FUNC"Failed to update state to messaging "
+ "register. RC: 0x%08X", rc);
+ }
+ return 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 rc = 0;
+
+ iv_majorStep = i_major;
+ iv_minorStep = i_minor;
+
+ rc = putscom_abs(PERV_SB_MSG_SCOM, iv_messagingReg);
+ if(rc)
+ {
+ SBE_ERROR(SBE_FUNC"Failed to update SBE step to messaging "
+ "register. RC: 0x%08X", rc);
+ }
+ return 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 rc = 0;
+
+ iv_sbeBooted = true;
+ rc = putscom_abs(PERV_SB_MSG_SCOM, iv_messagingReg);
+ if(rc)
+ {
+ SBE_ERROR(SBE_FUNC"Failed to update SBE ready state to "
+ "messaging register. RC: 0x%08X", rc);
+ }
+ return 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 rc = 0;
+ uint8_t l_set = i_set;
+ rc = getscom_abs(PERV_SCRATCH_REGISTER_3_SCOM, &iv_mbx3);
+ if(rc)
+ {
+ SBE_ERROR(SBE_FUNC"Failed read PERV_SCRATCH_REGISTER_3_SCOM "
+ "RC: 0x%08X", rc);
+ }
+
+ iv_mpiplMode = i_set;
+ PLAT_ATTR_INIT(ATTR_IS_MPIPL, Target<TARGET_TYPE_SYSTEM>(), l_set);
+ rc = putscom_abs(PERV_SCRATCH_REGISTER_3_SCOM, iv_mbx3);
+ if(rc)
+ {
+ SBE_ERROR(SBE_FUNC"Failed to set/clear MPIPL flag in "
+ "mbx reg. 3. RC: 0x%08X", rc);
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
+uint32_t SbeRegAccess::updateAsyncFFDCBit( bool i_on )
+{
+ #define SBE_FUNC "SbeRegAccess::updateAsyncFFDCBit "
+ uint32_t rc = 0;
+
+ iv_asyncFFDC = i_on;
+
+ rc = putscom_abs(PERV_SB_MSG_SCOM, iv_messagingReg);
+ if(rc)
+ {
+ SBE_ERROR(SBE_FUNC"Failed to update SBE Aync bit in message "
+ "register. RC: 0x%08X", rc);
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
diff --git a/src/sbefw/core/sberegaccess.H b/src/sbefw/core/sberegaccess.H
new file mode 100644
index 00000000..420cf795
--- /dev/null
+++ b/src/sbefw/core/sberegaccess.H
@@ -0,0 +1,302 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sberegaccess.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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 <stdint.h>
+#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()
+ {
+ return cv_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 Get the SBE previous State
+ *
+ * @return SBE previous State, sbeState enum
+ *
+ */
+ uint64_t getSbePrevState() const
+ {
+ return iv_prevState;
+ }
+
+
+ /**
+ * @brief Get the SBE major istep number
+ *
+ * @return SBE current major istep number
+ *
+ */
+ uint8_t getSbeMajorIstepNumber() const
+ {
+ return iv_majorStep;
+ }
+
+ /**
+ * @brief Update the SBE State as per the transition event
+ *
+ * @param [in] i_event Transition Event
+ */
+ void stateTransition(const sbeEvent &i_event);
+
+ /**
+ * @brief Update the async bit into the SBE messaging register. The
+ * function does a read-modify-write, so any bits other than the async
+ * bits are retained.
+ *
+ * @param [in] i_on True to turn on bit, false to turn off
+ *
+ * @return RC indicating success/failure.
+ *
+ */
+ uint32_t updateAsyncFFDCBit( bool i_on );
+ 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_asyncFFDC : 1;
+ uint64_t iv_reserved1 : 2;
+ uint64_t iv_prevState : 4;
+ uint64_t iv_currState : 4;
+ uint64_t iv_majorStep : 8; // Max major is 97
+ uint64_t iv_minorStep : 6; // Max minor is 34
+ uint64_t iv_reserved2 : 6; // Unused
+ 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;
+ static const uint64_t SBE_PERV_DEVICE_ID_REG_BIT58_MASK = 0x0000000000000020ULL;
+ static SbeRegAccess cv_instance;
+};
+#endif //__SBEFW_SBEREGACCESS_H
+
diff --git a/src/sbefw/core/sbescom.C b/src/sbefw/core/sbescom.C
new file mode 100644
index 00000000..7c4105a0
--- /dev/null
+++ b/src/sbefw/core/sbescom.C
@@ -0,0 +1,221 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbescom.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include <stdint.h>
+#include "sbe_sp_intf.H"
+#include "sbetrace.H"
+#include "plat_hw_access.H"
+#include "plat_target.H"
+#include "sbescom.H"
+#include "sbeSecurity.H"
+
+using namespace fapi2;
+/**
+ * @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
+};
+
+void checkIndirectAndDoScom( const bool i_isRead,
+ const uint64_t i_addr,
+ uint64_t & io_data,
+ sbeRespGenHdr_t *const o_hdr,
+ sbeResponseFfdc_t *const o_ffdc)
+{
+
+ #define SBE_FUNC " checkIndirectAndDoScom "
+ uint32_t elapsedIndScomTimeNs = 0;
+ uint64_t tempBuffer = io_data;
+ sbeScomType scomType = SBE_SCOM_TYPE_DIRECT;
+ ReturnCode fapiRc = FAPI2_RC_SUCCESS;
+ do
+ {
+ // If the indirect scom bit is 0, then doing a regular scom
+ if( (i_addr & DIRECT_SCOM_ADDR_MASK) == 0)
+ {
+ plat_target_handle_t l_hndl;
+ SBE_INFO(SBE_FUNC "Performing Direct scom.");
+ CHECK_SBE_SECURITY_RC_AND_BREAK_IF_NOT_SUCCESS(
+ static_cast<uint32_t>(i_addr),
+ (i_isRead ? SBE_SECURITY::READ : SBE_SECURITY::WRITE),
+ o_hdr->primaryStatus,
+ o_hdr->secondaryStatus)
+ if( i_isRead )
+ {
+ fapiRc = getscom_abs_wrap (&l_hndl, (uint32_t)i_addr,
+ & io_data);
+ }
+ else
+ {
+ fapiRc = putscom_abs_wrap (&l_hndl, (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");
+ o_hdr->primaryStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE;
+ o_hdr->secondaryStatus = 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;
+ plat_target_handle_t l_hndl;
+ CHECK_SBE_SECURITY_RC_AND_BREAK_IF_NOT_SUCCESS(
+ static_cast<uint32_t>(tempAddr),
+ (i_isRead ? SBE_SECURITY::READ : SBE_SECURITY::WRITE),
+ o_hdr->primaryStatus,
+ o_hdr->secondaryStatus)
+
+ // 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.
+ fapiRc = putscom_abs_wrap (&l_hndl, tempAddr, tempBuffer);
+
+ if( ( fapiRc != FAPI2_RC_SUCCESS ) ||
+ ( 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.
+ fapiRc = getscom_abs_wrap (&l_hndl, tempAddr, &(scomout.data64));
+
+ if( fapiRc != FAPI2_RC_SUCCESS) 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");
+ 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( fapiRc != FAPI2_RC_SUCCESS ) break;
+ if( ! scomout.done)
+ {
+ SBE_ERROR(SBE_FUNC "Indirect scom timeout.");
+ o_hdr->primaryStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE;
+ o_hdr->secondaryStatus = SBE_SEC_HW_OP_TIMEOUT;
+ break;
+ }
+
+ }while(0);
+
+ if (fapiRc != FAPI2_RC_SUCCESS)
+ {
+ o_hdr->primaryStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE;
+ o_hdr->secondaryStatus = SBE_SEC_PCB_PIB_ERR;
+ if(o_ffdc) o_ffdc->setRc(fapiRc);
+ }
+
+ SBE_DEBUG(SBE_FUNC "fapiRc:%u o_hdr->secondaryStatus:0x%08X", fapiRc, o_hdr->secondaryStatus);
+}
+
diff --git a/src/sbefw/core/sbescom.H b/src/sbefw/core/sbescom.H
new file mode 100644
index 00000000..5d242cdf
--- /dev/null
+++ b/src/sbefw/core/sbescom.H
@@ -0,0 +1,40 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbescom.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include "sbeSpMsg.H"
+/**
+ * @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[out] o_hdr response header object
+ * @param[out] o_ffdc ffdc object
+ *
+ */
+void checkIndirectAndDoScom( const bool i_isRead,
+ const uint64_t i_addr,
+ uint64_t & io_data,
+ sbeRespGenHdr_t *const o_hdr,
+ sbeResponseFfdc_t *const o_ffdc);
diff --git a/src/sbefw/core/sbestates.H b/src/sbefw/core/sbestates.H
new file mode 100644
index 00000000..4f97c363
--- /dev/null
+++ b/src/sbefw/core/sbestates.H
@@ -0,0 +1,63 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbestates.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/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_IPLING = 0x1, // IPL'ing - autonomous mode (transient)
+ SBE_STATE_ISTEP = 0x2, // ISTEP - Running IPL by steps (transient)
+ SBE_STATE_MPIPL = 0x3, // MPIPL
+ SBE_STATE_RUNTIME = 0x4, // SBE Runtime
+ SBE_STATE_DMT = 0x5, // Dead Man Timer State (transient)
+ SBE_STATE_DUMP = 0x6, // Dumping
+ SBE_STATE_FAILURE = 0x7, // Internal SBE failure
+ SBE_STATE_QUIESCE = 0x8, // Final state - needs SBE reset to get out
+
+ // Max States, Always keep it at the last of the enum and sequential
+ SBE_MAX_STATE = 0x9,
+ // 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
+};
+
+#endif //__SBEFW_SBESTATES_H
+
diff --git a/src/sbefw/core/sbetrace.H b/src/sbefw/core/sbetrace.H
new file mode 100644
index 00000000..5c3ea7b5
--- /dev/null
+++ b/src/sbefw/core/sbetrace.H
@@ -0,0 +1,75 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbetrace.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#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/core/sbeutil.C b/src/sbefw/core/sbeutil.C
new file mode 100644
index 00000000..bc53e7a4
--- /dev/null
+++ b/src/sbefw/core/sbeutil.C
@@ -0,0 +1,62 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeutil.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "sbeutil.H"
+#include "fapi2.H"
+#include "sbetrace.H"
+#include "sbeglobals.H"
+// Nest frequency array
+#include "p9_frequency_buckets.H"
+namespace SBE
+{
+ bool isSimics() __attribute__((alias("__isSimicsRunning")));
+ extern "C" void __isSimicsRunning() __attribute__ ((noinline));
+
+ void __isSimicsRunning()
+ {
+ asm volatile("li 3, 0");
+ SBE_MAGIC_INSTRUCTION(MAGIC_SIMICS_CHECK);
+ }
+
+ bool isSimicsRunning()
+ {
+ static bool simics = isSimics();
+ return simics;
+ }
+
+ void updatePkFreq()
+ {
+ #define SBE_FUNC "updatePkFreq "
+ using namespace fapi2;
+ Target<TARGET_TYPE_SYSTEM> sys;
+ uint8_t nestPllBkt = 0;
+ FAPI_ATTR_GET( ATTR_NEST_PLL_BUCKET, sys, nestPllBkt );
+ assert( nestPllBkt && (nestPllBkt <= NEST_PLL_FREQ_BUCKETS ));
+ SBE_GLOBAL->sbefreq = ( NEST_PLL_FREQ_LIST[ nestPllBkt - 1 ] * 1000 * 1000 )/
+ SBE::SBE_TO_NEST_FREQ_FACTOR;
+ SBE_INFO(SBE_FUNC"Setting new frequency:0x%08X", SBE_GLOBAL->sbefreq);
+ pk_timebase_freq_set(SBE_GLOBAL->sbefreq);
+ #undef SBE_FUNC
+ }
+}
+
diff --git a/src/sbefw/core/sbeutil.H b/src/sbefw/core/sbeutil.H
new file mode 100644
index 00000000..75ea07b5
--- /dev/null
+++ b/src/sbefw/core/sbeutil.H
@@ -0,0 +1,197 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbeutil.H $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef SBE_UTIL_H
+#define SBE_UTIL_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pk.h"
+#include "pk_api.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#define MASK_ZERO_L32B_UINT64(x) ((x) & 0xFFFFFFFF00000000ull)
+#define MASK_ZERO_H32B_UINT64(x) ((x) & 0x00000000FFFFFFFFull)
+#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; \
+}
+
+#define CHECK_SBE_SECURITY_RC_AND_BREAK_IF_NOT_SUCCESS(addr, op, prim, sec) \
+if (!SBE_SECURITY::isAllowed(addr, op)) \
+{ \
+ prim = SBE_PRI_UNSECURE_ACCESS_DENIED; \
+ sec = SBE_SEC_BLACKLISTED_REG_ACCESS; \
+ /* TODO via RTC 180983:Enable this once the BL/WL registers are settled */ \
+ /*break;*/ \
+}
+
+#define mfdec() \
+ ({volatile uint32_t l_dec; \
+ asm volatile ("mfdec %0" : "=r" (l_dec)); \
+ l_dec;})
+
+// To handle unused variables compilation error
+static inline void UNUSED(int dummy, ...) {}
+
+// Magic instruction
+
+/** @brief This is a special assembler instruction that is a nop on
+ * regular hardware, but has special meaning to Simics. Code that
+ * executes this instruction in Simics will cause a "hap," a
+ * Simics term. If there is no hap handler registered, and magic
+ * breakpoints have not been enabled with
+ * simics> enable-magic-breakpoint
+ * then this instruction is also a nop in Simics.
+ *
+ * If magic breakpoints are enabled, and there is no hap handler, then
+ * when SBE code executes this instruction in Simics, Simics will
+ * stop the simulation. (Prompt changes from running> to simics> )
+ *
+ * If a hap is registered, then Simics will call the hap handler. Hap
+ * handlers are written in Python, and the best place for them is
+ *
+ * src/tools/debug//simics-debug-framework.py
+ *
+ * Sample code to register the hap handler:
+ * # arg contains the integer parameter n passed to MAGIC_INSTRUCTION(n)
+ * def magic_instruction_callback(user_arg, cpu, arg):
+ * # print to console works...
+ * print "Hit magic instruction ", arg
+ * # Or else stop the simulation...
+ * SIM_break_simulation( "Stopped at magic instruction" )
+ *
+ * # Register the magic instruction callback.
+ * SIM_hap_add_callback( "Core_Magic_Instruction",
+ * magic_instruction_callback, None )
+ *
+ * # Better to register the SBE range 8000-8190
+ * # so that PHYP and others won't be affected.
+ * SIM_hap_add_callback_range( "Core_Magic_Instruction",
+ * magic_instruction_callback, None, 8000, 8190 )
+ *
+ * The argument n is an integer from 0..8191 which Simics passes to the hap
+ * handler in parameter 3, or "arg" in the sample code above.
+ */
+__attribute__((always_inline))
+inline void SBE_MAGIC_INSTRUCTION(int _n)
+{
+ register int n = _n;
+ asm volatile("rlwimi %0,%0,0,%1,%2" \
+ :: "i" (((n) >> 8) & 0x1f), \
+ "i" (((n) >> 4) & 0xf), \
+ "i" ((((n) >> 0) & 0xf) | 16));
+}
+
+// Macro to execute HWP
+#ifdef SEEPROM_IMAGE
+#define SBE_EXEC_HWP_NOARG(...) SBE_EXEC_HWP(__VA_ARGS__)
+#define SBE_EXEC_HWP(fapiRc, hwp, ...) \
+{ \
+ fapiRc = hwp(__VA_ARGS__); \
+}
+#else
+#define SBE_EXEC_HWP_NOARG(fapiRc, hwp) \
+{ \
+ SBE_INFO("Procedure not present in the image:No-Op"); \
+ fapiRc = FAPI2_RC_SUCCESS; \
+}
+#define SBE_EXEC_HWP(fapiRc, hwp, ...) \
+{ \
+ /* handling unused variables */ \
+ UNUSED(0, __VA_ARGS__); \
+ SBE_INFO("Procedure not present in the image:No-Op"); \
+ fapiRc = FAPI2_RC_SUCCESS; \
+}
+#endif
+
+void sbeHandleFifoResponse (const uint32_t i_rc);
+
+void sbeHandlePsuResponse (const uint32_t i_rc);
+
+namespace SBE
+{
+
+ // enum for magic instructions
+ enum
+ {
+ MAGIC_SIMICS_CHECK = 8000, // check if code is running on simics
+ };
+ // Nest to SBE frequency ratio
+ static const uint8_t SBE_TO_NEST_FREQ_FACTOR = 4;
+
+ // 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));
+ }
+
+ /*@brief - checks if sbe is running on simics
+ *
+ * @return - True if sbe is running on simics , false otherwise
+ */
+ bool isSimicsRunning();
+
+ /*@brief - Update the pk frequcy as per NEST PLL bucket
+ *
+ * @return - void
+ */
+ void updatePkFreq();
+
+} // namespace SBE
+#endif //SBE_UTIL_H
diff --git a/src/sbefw/core/vector b/src/sbefw/core/vector
new file mode 100644
index 00000000..bbb0818d
--- /dev/null
+++ b/src/sbefw/core/vector
@@ -0,0 +1,397 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/vector $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#ifndef stl_vector
+#define stl_vector
+
+/**
+ * @file vector
+ * @brief simple stl vector template class declaration.
+ */
+
+#include <stddef.h>
+
+#if !defined( __STDC_LIMIT_MACROS)
+#define __STDC_LIMIT_MACROS
+#endif
+#include <stdint.h>
+#include <pool.H>
+#include <assert.h>
+#include <new>
+namespace std
+{
+
+ /**
+ * @class vector
+ * subset of stl vector
+ * @note Does not support allocators, reverse iterators.
+ */
+ template <class T>
+ 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<T>&& 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<T>& operator=(const vector<T>&& 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<T>& x);
+ vector<T>& operator=(const vector<T>& x);
+};
+
+}; // end namespace std
+
+
+#endif
+/* vim: set filetype=cpp : */
OpenPOWER on IntegriCloud