summaryrefslogtreecommitdiffstats
path: root/src/sbefw/core/sbemain.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/sbefw/core/sbemain.C')
-rw-r--r--src/sbefw/core/sbemain.C341
1 files changed, 341 insertions, 0 deletions
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;
+}
OpenPOWER on IntegriCloud