diff options
Diffstat (limited to 'src/sbefw/core/sbemain.C')
-rw-r--r-- | src/sbefw/core/sbemain.C | 341 |
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; +} |