diff options
author | William Bryan <wilbryan@us.ibm.com> | 2016-04-18 17:07:34 -0500 |
---|---|---|
committer | William A. Bryan <wilbryan@us.ibm.com> | 2016-06-13 19:18:11 -0400 |
commit | a12f5be3e904bf5bb7aabb978f5e4d0cf1e8b969 (patch) | |
tree | 08e5fe4298b301d7441bbb4d450432651aefc5e6 /src | |
parent | dd417235fda3a7086940b974780193e51370367c (diff) | |
download | talos-occ-a12f5be3e904bf5bb7aabb978f5e4d0cf1e8b969.tar.gz talos-occ-a12f5be3e904bf5bb7aabb978f5e4d0cf1e8b969.zip |
Update SSX to latest in EKB
RTC: 132999
Change-Id: I29478c074e3086e0bf09b402d55782e03cb1f787
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/23394
Tested-by: FSP CI Jenkins
Reviewed-by: Wael El-Essawy <welessa@us.ibm.com>
Diffstat (limited to 'src')
84 files changed, 2762 insertions, 1972 deletions
diff --git a/src/occ_405/dcom/dcom.c b/src/occ_405/dcom/dcom.c index eed1cee..1016c47 100755 --- a/src/occ_405/dcom/dcom.c +++ b/src/occ_405/dcom/dcom.c @@ -27,6 +27,7 @@ #define _DCOM_C //#include <pgp_pmc.h> +#include "ssx.h" #include "occhw_pba.h" #include <rtls.h> #include <apss.h> diff --git a/src/occ_405/dcom/dcomMasterRx.c b/src/occ_405/dcom/dcomMasterRx.c index e1a7d30..37a0a31 100644 --- a/src/occ_405/dcom/dcomMasterRx.c +++ b/src/occ_405/dcom/dcomMasterRx.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -25,6 +25,8 @@ #ifndef _DCOMMASTERRX_C #define _DCOMMASTERRX_C + +#include "ssx.h" #include "occhw_pba.h" #include <rtls.h> #include <apss.h> diff --git a/src/occ_405/dcom/dcomMasterTx.c b/src/occ_405/dcom/dcomMasterTx.c index ad1beba..58af809 100644 --- a/src/occ_405/dcom/dcomMasterTx.c +++ b/src/occ_405/dcom/dcomMasterTx.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -26,6 +26,7 @@ #ifndef _DCOMMASTERTX_C #define _DCOMMASTERTX_C +#include "ssx.h" #include "occhw_pba.h" #include <rtls.h> #include <apss.h> diff --git a/src/occ_405/dcom/dcomSlaveRx.c b/src/occ_405/dcom/dcomSlaveRx.c index 10af964..7ef788a 100644 --- a/src/occ_405/dcom/dcomSlaveRx.c +++ b/src/occ_405/dcom/dcomSlaveRx.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -25,6 +25,8 @@ #ifndef _DCOMSLAVERX_C #define _DCOMSLAVERX_C + +#include "ssx.h" #include "occhw_pba.h" #include <rtls.h> #include <apss.h> diff --git a/src/occ_405/dcom/dcomSlaveTx.c b/src/occ_405/dcom/dcomSlaveTx.c index 3f05b08..dbda10e 100755 --- a/src/occ_405/dcom/dcomSlaveTx.c +++ b/src/occ_405/dcom/dcomSlaveTx.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -25,6 +25,7 @@ #ifndef _DCOMSLAVETX_C #define _DCOMSLAVETX_C +#include "ssx.h" #include "occhw_pba.h" #include <rtls.h> #include <apss.h> diff --git a/src/occ_405/dcom/dcom_thread.c b/src/occ_405/dcom/dcom_thread.c index c151482..f6eda92 100755 --- a/src/occ_405/dcom/dcom_thread.c +++ b/src/occ_405/dcom/dcom_thread.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -26,6 +26,7 @@ #ifndef _DCOM_THREAD_C #define _DCOM_THREAD_C +#include "ssx.h" #include "occhw_pba.h" #include <rtls.h> #include <apss.h> diff --git a/src/ssx/occhw/Makefile b/src/ssx/occhw/Makefile index c16da5b..45101df 100644 --- a/src/ssx/occhw/Makefile +++ b/src/ssx/occhw/Makefile @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2015 +# Contributors Listed Below - COPYRIGHT 2015,2016 # [+] International Business Machines Corp. # # diff --git a/src/ssx/occhw/occhw.h b/src/ssx/occhw/occhw.h index c0f11df..fdaf97c 100644 --- a/src/ssx/occhw/occhw.h +++ b/src/ssx/occhw/occhw.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -35,12 +35,12 @@ /// \brief The OCCHW environment for SSX. // This is a 'circular' reference in SSX, but included here to simplify PGAS -// programming. +// programming. #ifndef HWMACRO_OCC -#define HWMACRO_OCC -#include "ppc405.h" -#endif + #define HWMACRO_OCC + #include "ppc405.h" +#endif // Can't include this here due to ordering issues. It's included in // ppc405_irq.h. @@ -83,7 +83,7 @@ /// The final 128MB of memory (the SRAM) is mapped both I- and /// D-cacheable. The other 7 high-memory regions aliased by the SRAM remain /// uncacheable, however SRAM alias region 29 is marked write-through. -/// +/// /// Low memory addresses (direct-map Mainstore via PBA) are I-cacheable /// but not D-cacheable to improve predicatability of execution times. /// However, we should not execute from mainstore after initialization. @@ -95,27 +95,27 @@ /// @{ #ifndef PPC405_ICCR_INITIAL -#define PPC405_ICCR_INITIAL 0xff000001 + #define PPC405_ICCR_INITIAL 0xff000001 #endif #ifndef PPC405_DCCR_INITIAL -#define PPC405_DCCR_INITIAL 0x00000001 + #define PPC405_DCCR_INITIAL 0x00000001 #endif #ifndef PPC405_DCWR_INITIAL -#define PPC405_DCWR_INITIAL 0x00000004 + #define PPC405_DCWR_INITIAL 0x00000004 #endif #ifndef PPC405_SGR_INITIAL -#define PPC405_SGR_INITIAL 0x00ff0000 + #define PPC405_SGR_INITIAL 0x00ff0000 #endif #ifndef PPC405_SU0R_INITIAL -#define PPC405_SU0R_INITIAL 0x00000000 + #define PPC405_SU0R_INITIAL 0x00000000 #endif #ifndef PPC405_SLER_INITIAL -#define PPC405_SLER_INITIAL 0x00000000 + #define PPC405_SLER_INITIAL 0x00000000 #endif /// @} @@ -157,7 +157,7 @@ #ifndef __ASSEMBLER__ -/// \page noncacheable_support Non-cacheable modes for OCCHW +/// \page noncacheable_support Non-cacheable modes for OCCHW /// /// In order to support evaluation of cache management strategies on /// performance, DMA buffers read/written by DMA devices can be declared as @@ -181,7 +181,7 @@ #ifndef NONCACHEABLE_SUPPORT -#define NONCACHEABLE_SUPPORT 0 + #define NONCACHEABLE_SUPPORT 0 #endif @@ -263,11 +263,11 @@ /// Flush/invalidate a region of memory #if NONCACHEABLE_SUPPORT -#define FLUSH(p, n) do {} while (0) -#define INVALIDATE(p, n) do {} while (0) + #define FLUSH(p, n) do {} while (0) + #define INVALIDATE(p, n) do {} while (0) #else -#define FLUSH(p, n) do {dcache_flush((p), (n));} while (0) -#define INVALIDATE(p, n) do {dcache_invalidate((p), (n));} while (0) + #define FLUSH(p, n) do {dcache_flush((p), (n));} while (0) + #define INVALIDATE(p, n) do {dcache_invalidate((p), (n));} while (0) #endif /* NONCACHEABLE_SUPPORT */ @@ -287,7 +287,8 @@ /// This type definition is considered a required definition for a port of /// SSX. -typedef struct { +typedef struct +{ char bogus[9]; } SsxLinkerSymbol; @@ -341,7 +342,7 @@ extern Ppc405MmuMap G_applet1_mmu_map; // 31 | 0xF8000000 - 0xffffffff (overlaps SRAM) #define USE_GENERIC_DCACHE_FLUSH_ALL 0 -#define OCCHW_FLUSH_ZERO_ADDRESS 0x20000000 -#define OCCHW_FLUSH_ZERO_DCCR 0x08000000 +#define OCCHW_FLUSH_ZERO_ADDRESS 0x40000000 +#define OCCHW_FLUSH_ZERO_DCCR 0x00800000 #endif /* __OCCHW_H__ */ diff --git a/src/ssx/occhw/occhw_async.c b/src/ssx/occhw/occhw_async.c index ae3273b..3efac8e 100644 --- a/src/ssx/occhw/occhw_async.c +++ b/src/ssx/occhw/occhw_async.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -109,7 +109,7 @@ /// and any thread pending on request completion has been maxde runnable. /// /// Normally the application should see the request state (\a request->state) -/// ASYNC_REQUEST_STATE_COMPLETE and a callback return code +/// ASYNC_REQUEST_STATE_COMPLETE and a callback return code /// (\a request=->callback_rc) of 0 which indicates that the job and callback /// both completed normally. If the request did not complete normally it /// could be due to one of several reasons. For further analysis the request @@ -163,7 +163,7 @@ static SsxDeque G_async_callback_queue; SsxDeque G_ipc_deferred_queue; //////////////////////////////////////////////////////////////////////////// -// FFDC +// FFDC //////////////////////////////////////////////////////////////////////////// /// Collect FFDC for the PLB (OCI) arbiter @@ -175,7 +175,7 @@ SsxDeque G_ipc_deferred_queue; /// Note: The PEAR and PESR hold error information for all OCI masters /// _except_ the OCC ICU and DCU. ICU and DCU errors are in the STO_PESR and /// STO_PEAR. Currently there is no need to collect those DCRs for 'async' -/// errors. +/// errors. void oci_ffdc(OciFfdc* ffdc, int master_id) @@ -209,11 +209,13 @@ oci_ffdc(OciFfdc* ffdc, int master_id) // captured the first time the request is run on the device. static inline int -async_request_run(AsyncRequest *request) +async_request_run(AsyncRequest* request) { - if (request->state != ASYNC_REQUEST_STATE_RUNNING) { + if (request->state != ASYNC_REQUEST_STATE_RUNNING) + { request->start_time = ssx_timebase_get(); } + request->state = ASYNC_REQUEST_STATE_RUNNING; return request->run_method(request); } @@ -229,7 +231,7 @@ async_request_run(AsyncRequest *request) // AsyncQueue objects. int -async_queue_create(AsyncQueue *queue, AsyncEngine engine) +async_queue_create(AsyncQueue* queue, AsyncEngine engine) { ssx_deque_sentinel_create(&(queue->deque)); queue->current = 0; @@ -244,7 +246,7 @@ async_queue_create(AsyncQueue *queue, AsyncEngine engine) // and async_request_deque(). static void -async_request_complete(AsyncRequest *request) +async_request_complete(AsyncRequest* request) { SsxMachineContext ctx; AsyncRequestCallback callback; @@ -256,19 +258,25 @@ async_request_complete(AsyncRequest *request) // Note that 'completed' here means only that the callback is complete. callback = request->callback; - if (!callback) { + + if (!callback) + { completed = 1; - } else if ((request->options & ASYNC_CALLBACK_IMMEDIATE) || - ((request->options & ASYNC_CALLBACK_NONCRITICAL) && - !__ssx_kernel_context_critical_interrupt())) { + } + else if ((request->options & ASYNC_CALLBACK_IMMEDIATE) || + ((request->options & ASYNC_CALLBACK_NONCRITICAL) && + !__ssx_kernel_context_critical_interrupt())) + { request->state = ASYNC_REQUEST_STATE_CALLBACK_RUNNING; request->callback_rc = callback(request->arg); completed = 1; - } else { + } + else + { request->state = ASYNC_REQUEST_STATE_CALLBACK_QUEUED; completed = 0; @@ -278,22 +286,29 @@ async_request_complete(AsyncRequest *request) // If the callback completed then we go ahead and cancel any timeout // and/or wake the thread if possible. In critical interrupt contexts // we always have to defer these operations, so we may lose 'complete' - // status. + // status. - if (completed && + if (completed && ((request->timeout != SSX_WAIT_FOREVER) || - (request->options & ASYNC_REQUEST_BLOCKING))) { + (request->options & ASYNC_REQUEST_BLOCKING))) + { - if (__ssx_kernel_context_critical_interrupt()) { + if (__ssx_kernel_context_critical_interrupt()) + { request->state = ASYNC_REQUEST_STATE_POSTPROCESSING; completed = 0; - } else { - if (request->timeout != SSX_WAIT_FOREVER) { + } + else + { + if (request->timeout != SSX_WAIT_FOREVER) + { ssx_timer_cancel(&(request->timer)); } - if (request->options & ASYNC_REQUEST_BLOCKING) { + + if (request->options & ASYNC_REQUEST_BLOCKING) + { ssx_semaphore_post(&(request->sem)); } } @@ -303,18 +318,24 @@ async_request_complete(AsyncRequest *request) // A truly completed job gets its completion state here. Otherwise we // have to schedule the deferred postprocessing. - if (completed) { - + if (completed) + { + request->state = request->completion_state; - } else { + } + else + { ssx_critical_section_enter(SSX_CRITICAL, &ctx); - if (request->options & ASYNC_CALLBACK_PRIORITY) { + if (request->options & ASYNC_CALLBACK_PRIORITY) + { ssx_deque_push_front(&G_async_callback_queue, &(request->deque)); - } else { + } + else + { ssx_deque_push_back(&G_async_callback_queue, &(request->deque)); } @@ -346,30 +367,35 @@ async_request_complete(AsyncRequest *request) // interrupts for that queue. void -async_handler(AsyncQueue *queue) +async_handler(AsyncQueue* queue) { - AsyncRequest *finished, *current; + AsyncRequest* finished, *current; int rc; // This loop is repeated as long as any job started in a loop completes // immediately. - do { + do + { // This API may be called on an idle queue, which indicates that we // should simply start the job on the head of the queue. Otherwise // save a pointer to the job that just finished and update its // end_time. - if (queue->state == ASYNC_QUEUE_STATE_IDLE) { + if (queue->state == ASYNC_QUEUE_STATE_IDLE) + { finished = 0; - } else { + } + else + { - finished = (AsyncRequest *)(queue->current); + finished = (AsyncRequest*)(queue->current); - if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) { + if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) + { SSX_PANIC(ASYNC_PHANTOM_INTERRUPT); } @@ -380,22 +406,28 @@ async_handler(AsyncQueue *queue) // If the queue is in an error state we will not schedule any further // jobs on this queue. Otherwise we start the next job running on the - // engine. + // engine. - if (queue->state == ASYNC_QUEUE_STATE_ERROR) { + if (queue->state == ASYNC_QUEUE_STATE_ERROR) + { queue->current = 0; rc = 0; - } else { + } + else + { - current = (AsyncRequest *)ssx_deque_pop_front(&(queue->deque)); + current = (AsyncRequest*)ssx_deque_pop_front(&(queue->deque)); queue->current = current; - if (current) { + if (current) + { queue->state = ASYNC_QUEUE_STATE_RUNNING; rc = async_request_run(current); - } else { + } + else + { queue->state = ASYNC_QUEUE_STATE_IDLE; rc = 0; } @@ -407,12 +439,14 @@ async_handler(AsyncQueue *queue) // next loop (it would have given an rc == // -ASYNC_REQUEST_COMPLETE). Otherwise complete the request. - if (finished != 0) { + if (finished != 0) + { async_request_complete(finished); } - } while (rc == -ASYNC_REQUEST_COMPLETE); + } + while (rc == -ASYNC_REQUEST_COMPLETE); } @@ -443,8 +477,8 @@ async_handler(AsyncQueue *queue) /// way at entry. /// /// \retval -ASYNC_REQUEST_NOT_COMPLETE This code is returned for requests that -/// do not complete successfully, but only if ASYNC_REQUEST_BLOCKING is -/// specified. The caller will need to examine the request state if necessary +/// do not complete successfully, but only if ASYNC_REQUEST_BLOCKING is +/// specified. The caller will need to examine the request state if necessary /// to determine whether the request failed, was cancelled or timed out. /// /// \todo Consider making the critical section priority depend on the device @@ -453,44 +487,56 @@ async_handler(AsyncQueue *queue) /// section. int -async_request_schedule(AsyncRequest *request) +async_request_schedule(AsyncRequest* request) { SsxMachineContext ctx = SSX_THREAD_MACHINE_CONTEXT_DEFAULT; // For GCC - AsyncQueue *queue; + AsyncQueue* queue; int rc; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(request == 0, ASYNC_INVALID_OBJECT_SCHEDULE); } rc = 0; ssx_critical_section_enter(SSX_CRITICAL, &ctx); - do { + do + { // Check to insure the request is idle (which check must be done in // the critical section), then start any required timeout. - if (SSX_ERROR_CHECK_API) { - if (!async_request_is_idle(request)) { + if (SSX_ERROR_CHECK_API) + { + if (!async_request_is_idle(request)) + { rc = -ASYNC_REQUEST_NOT_IDLE; break; } } - if (request->timeout != SSX_WAIT_FOREVER) { + if (request->timeout != SSX_WAIT_FOREVER) + { rc = ssx_timer_schedule(&(request->timer), request->timeout, 0); - if (rc) break; + + if (rc) + { + break; + } } - + // Enqueue the request and initialize the request state. queue = request->queue; - if (request->options & ASYNC_REQUEST_PRIORITY) { + if (request->options & ASYNC_REQUEST_PRIORITY) + { ssx_deque_push_front(&(queue->deque), &(request->deque)); - } else { + } + else + { ssx_deque_push_back(&(queue->deque), &(request->deque)); } @@ -502,21 +548,29 @@ async_request_schedule(AsyncRequest *request) // If the queue is idle, call the async_handler() to start the job. // Then block the calling thread if required. - if (queue->state == ASYNC_QUEUE_STATE_IDLE) { + if (queue->state == ASYNC_QUEUE_STATE_IDLE) + { async_handler(queue); } - if (request->options & ASYNC_REQUEST_BLOCKING) { + if (request->options & ASYNC_REQUEST_BLOCKING) + { rc = ssx_semaphore_pend(&(request->sem), SSX_WAIT_FOREVER); - if (rc) break; - if (!async_request_completed(request)) { + if (rc) + { + break; + } + + if (!async_request_completed(request)) + { rc = -ASYNC_REQUEST_NOT_COMPLETE; break; } } - } while (0); + } + while (0); ssx_critical_section_exit(&ctx); @@ -538,19 +592,23 @@ async_request_schedule(AsyncRequest *request) void async_error_handler(AsyncQueue* queue, uint8_t completion_state) { - AsyncRequest *finished; + AsyncRequest* finished; - finished = (AsyncRequest *)(queue->current); + finished = (AsyncRequest*)(queue->current); - if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) { + if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) + { SSX_PANIC(ASYNC_PHANTOM_ERROR); } - if (finished->error_method) { - if (finished->error_method(finished)) { + if (finished->error_method) + { + if (finished->error_method(finished)) + { queue->state = ASYNC_QUEUE_STATE_ERROR; } } + finished->abort_state = finished->state; finished->completion_state = completion_state; async_handler(queue); @@ -580,7 +638,7 @@ async_request_dequeue(AsyncRequest* request, uint8_t completion_state) // Time out an AsyncRequest // // This is an internal API, the timer callback used to time out long-running -// AsyncRequest. +// AsyncRequest. // // This timer callback must run in an SSX_CRITICAL critical section to // guarantee atomic access to the AsyncRequest object. @@ -588,7 +646,7 @@ async_request_dequeue(AsyncRequest* request, uint8_t completion_state) static void async_timeout(void* arg) { - AsyncRequest *request = (AsyncRequest*)arg; + AsyncRequest* request = (AsyncRequest*)arg; SsxMachineContext ctx; ssx_critical_section_enter(SSX_CRITICAL, &ctx); @@ -596,7 +654,8 @@ async_timeout(void* arg) // The behavior at timeout depends on the mode. We'll handle the cases // from easiest to hardest. - if (request->state & ASYNC_REQUEST_CALLBACK_GROUP) { + if (request->state & ASYNC_REQUEST_CALLBACK_GROUP) + { // If the request has already queued or is running the callback (which // could happen due to interrupt interleaving) then the request is @@ -604,24 +663,30 @@ async_timeout(void* arg) // ssx_timer_cancel() to cancel the timer. So there's nothing to do. - } else if (request->state & ASYNC_REQUEST_IDLE_GROUP) { + } + else if (request->state & ASYNC_REQUEST_IDLE_GROUP) + { // If the request is idle we panic - This can't happen as it would // indicate that the timer was not cancelled when the request - // finished. + // finished. SSX_PANIC(ASYNC_TIMEOUT_BUG); - } else if (request->state & ASYNC_REQUEST_QUEUED_GROUP) { + } + else if (request->state & ASYNC_REQUEST_QUEUED_GROUP) + { // If the request is still in the queue then we can simply cancel it, // which includes running the callback. - async_request_dequeue(request, ASYNC_REQUEST_STATE_TIMED_OUT); + async_request_dequeue(request, ASYNC_REQUEST_STATE_TIMED_OUT); - } else if (request->state & ASYNC_REQUEST_RUNNING_GROUP) { + } + else if (request->state & ASYNC_REQUEST_RUNNING_GROUP) + { // If the request is running on the hardware, then we need to call // the async_error_handler() to remove the job and restart the @@ -630,7 +695,9 @@ async_timeout(void* arg) async_error_handler(request->queue, ASYNC_REQUEST_STATE_TIMED_OUT); - } else { + } + else + { SSX_PANIC(ASYNC_INVALID_STATE); @@ -646,7 +713,7 @@ async_timeout(void* arg) // API does some error checking, and any errors will be returned by the // higher-level call. // -// \retval -ASYNC_INVALID_OBJECT_REQUEST The \a request or \a queue was +// \retval -ASYNC_INVALID_OBJECT_REQUEST The \a request or \a queue was /// null (0). // // \retval -ASYNC_INVALID_OPTIONS The \a options argument contains invalid @@ -658,23 +725,24 @@ async_timeout(void* arg) // non-NULL callback, but no protocol for running the callback was specified. int -async_request_create(AsyncRequest *request, - AsyncQueue *queue, +async_request_create(AsyncRequest* request, + AsyncQueue* queue, AsyncRunMethod run_method, AsyncErrorMethod error_method, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options) { - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((request == 0) || (queue == 0), - ASYNC_INVALID_OBJECT_REQUEST); + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((request == 0) || (queue == 0), + ASYNC_INVALID_OBJECT_REQUEST); SSX_ERROR_IF((options & ~ASYNC_GENERIC_OPTIONS) || (__builtin_popcount(options & ASYNC_CALLBACK_OPTIONS) > 1), ASYNC_INVALID_OPTIONS); SSX_ERROR_IF(run_method == 0, ASYNC_INVALID_ARGUMENT); - SSX_ERROR_IF((callback != 0) && + SSX_ERROR_IF((callback != 0) && ((options & ASYNC_CALLBACK_OPTIONS) == 0), ASYNC_CALLBACK_PROTOCOL_UNSPECIFIED); } @@ -688,12 +756,14 @@ async_request_create(AsyncRequest *request, request->callback = callback; request->arg = arg; request->options = options; - - if (request->timeout != SSX_WAIT_FOREVER) { + + if (request->timeout != SSX_WAIT_FOREVER) + { ssx_timer_create(&(request->timer), async_timeout, (void*)request); } - if (options & ASYNC_REQUEST_BLOCKING) { + if (options & ASYNC_REQUEST_BLOCKING) + { ssx_semaphore_create(&(request->sem), 0, 1); } @@ -713,7 +783,7 @@ async_request_create(AsyncRequest *request, /// request, or NULL (0) is this data is not required. /// /// \retval 0 The request contains valid timestamps and they have been -/// returned. +/// returned. /// /// \retval -ASYNC_INVALID_TIMESTAMPS The caller's timestamps have been /// updated, but the timestamps are fully or partially invalid. This could be @@ -733,17 +803,23 @@ async_request_timestamps_get(AsyncRequest* request, ssx_critical_section_enter(SSX_CRITICAL, &ctx); - if (start_time) { + if (start_time) + { *start_time = request->start_time; } - if (end_time) { + + if (end_time) + { *end_time = request->end_time; } if ((request->state & ASYNC_REQUEST_IDLE_GROUP) && - (request->state != ASYNC_REQUEST_STATE_INITIALIZED)) { + (request->state != ASYNC_REQUEST_STATE_INITIALIZED)) + { rc = 0; - } else { + } + else + { rc = -ASYNC_INVALID_TIMESTAMPS; } @@ -761,7 +837,7 @@ async_request_timestamps_get(AsyncRequest* request, /// start time) computed from the timestamps of \a request. /// /// \retval 0 The request contains valid timestamps and they have been -/// returned. +/// returned. /// /// \retval -ASYNC_INVALID_TIMESTAMPS The latancy has been computed but may be /// invalid. This could be due to several reasons: @@ -785,7 +861,7 @@ async_request_latency(AsyncRequest* request, SsxTimebase* latency) // Dump an AsyncRequest #if 0 void -async_request_printk(AsyncRequest *request) +async_request_printk(AsyncRequest* request) { printk("----------------------------------------\n"); printk("-- AsyncRequest @ %p\n", request); @@ -848,50 +924,60 @@ SSX_IRQ_FAST2FULL(async_callback_handler, async_callback_handler_full); void async_request_finalize(AsyncRequest* request) { - if (request->state == ASYNC_REQUEST_STATE_CALLBACK_QUEUED) { + if (request->state == ASYNC_REQUEST_STATE_CALLBACK_QUEUED) + { request->state = ASYNC_REQUEST_STATE_CALLBACK_RUNNING; - if (request->options & ASYNC_CALLBACK_DEFERRED) { + if (request->options & ASYNC_CALLBACK_DEFERRED) + { ssx_interrupt_preemption_enable(); request->callback_rc = request->callback(request->arg); - } else { + } + else + { request->callback_rc = request->callback(request->arg); ssx_interrupt_preemption_enable(); } + ssx_interrupt_preemption_disable(); } request->state = request->completion_state; - if (request->timeout != SSX_WAIT_FOREVER) { + if (request->timeout != SSX_WAIT_FOREVER) + { ssx_timer_cancel(&(request->timer)); } - if (request->options & ASYNC_REQUEST_BLOCKING) { + if (request->options & ASYNC_REQUEST_BLOCKING) + { ssx_semaphore_post(&(request->sem)); } } void -async_callback_handler_full(void *arg, SsxIrqId irq, int priority) +async_callback_handler_full(void* arg, SsxIrqId irq, int priority) { SsxMachineContext ctx; - AsyncRequest *request; - ipc_msg_t *msg; + AsyncRequest* request; + ipc_msg_t* msg; ssx_irq_disable(irq); //Check for any async callbacks first - do { + do + { ssx_critical_section_enter(SSX_CRITICAL, &ctx); - request = (AsyncRequest *)ssx_deque_pop_front(&G_async_callback_queue); - if (!request) { + request = (AsyncRequest*)ssx_deque_pop_front(&G_async_callback_queue); + + if (!request) + { break; } @@ -899,29 +985,34 @@ async_callback_handler_full(void *arg, SsxIrqId irq, int priority) async_request_finalize(request); - } while (1); + } + while (1); ssx_critical_section_exit(&ctx); //Next, check for any deferred IPC messages - do { + do + { ssx_critical_section_enter(SSX_CRITICAL, &ctx); - msg = (ipc_msg_t *)ssx_deque_pop_front(&G_ipc_deferred_queue); - if (!msg) { + msg = (ipc_msg_t*)ssx_deque_pop_front(&G_ipc_deferred_queue); + + if (!msg) + { ssx_irq_status_clear(irq); break; } ssx_critical_section_exit(&ctx); -void ipc_process_msg(ipc_msg_t* msg); + void ipc_process_msg(ipc_msg_t* msg); //handle the command or response message in a noncritical context ipc_process_msg(msg); - } while (1); + } + while (1); ssx_critical_section_exit(&ctx); ssx_irq_enable(irq); @@ -942,7 +1033,7 @@ void ipc_process_msg(ipc_msg_t* msg); void async_edge_handler_setup(SsxIrqHandler handler, - void *arg, + void* arg, SsxIrqId irq, int priority) { @@ -957,7 +1048,7 @@ async_edge_handler_setup(SsxIrqHandler handler, void async_level_handler_setup(SsxIrqHandler handler, - void *arg, + void* arg, SsxIrqId irq, int priority, int polarity) diff --git a/src/ssx/occhw/occhw_async.h b/src/ssx/occhw/occhw_async.h index be2996f..2c3e842 100644 --- a/src/ssx/occhw/occhw_async.h +++ b/src/ssx/occhw/occhw_async.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -93,7 +93,7 @@ #ifndef __ASSEMBLER__ -typedef uint8_t AsyncEngine; + typedef uint8_t AsyncEngine; #endif /* __ASSEMBLER__ */ @@ -113,7 +113,8 @@ typedef uint8_t AsyncEngine; /// master on the OCI (SLW/GPE/OCB/PBA). Note that OCI errors from the 405 /// core will cause an immediate machine check exception. -typedef struct { +typedef struct +{ /// PLB arbiter Error Address Register /// @@ -236,11 +237,11 @@ oci_ffdc(OciFfdc* ffdc, int master_id); struct AsyncRequest; struct AsyncQueue; -typedef int (*AsyncRunMethod)(struct AsyncRequest *request); +typedef int (*AsyncRunMethod)(struct AsyncRequest* request); -typedef int (*AsyncErrorMethod)(struct AsyncRequest *request); +typedef int (*AsyncErrorMethod)(struct AsyncRequest* request); -typedef int (*AsyncRequestCallback)(void *); +typedef int (*AsyncRequestCallback)(void*); /// A generic request for the asynchronous request drivers /// @@ -266,7 +267,8 @@ typedef int (*AsyncRequestCallback)(void *); /// requests. If the \a error_method returns a non-0 code then the error is /// considered fatal and the queue stops. -typedef struct AsyncRequest { +typedef struct AsyncRequest +{ /// Generic queue management - the "base class" SsxDeque deque; @@ -297,7 +299,7 @@ typedef struct AsyncRequest { SsxTimer timer; /// The engine queue the request is/was scheduled on - struct AsyncQueue *queue; + struct AsyncQueue* queue; /// The "virtual" run method for the class AsyncRunMethod run_method; @@ -314,7 +316,7 @@ typedef struct AsyncRequest { AsyncRequestCallback callback; /// The argument of the callback - void *arg; + void* arg; /// The timeout value /// @@ -367,13 +369,13 @@ typedef struct AsyncRequest { int -async_request_create(AsyncRequest *request, - struct AsyncQueue *queue, +async_request_create(AsyncRequest* request, + struct AsyncQueue* queue, AsyncRunMethod run_method, AsyncErrorMethod error_method, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options); void @@ -395,7 +397,7 @@ async_request_finalize(AsyncRequest* request); /// \retval 1 The request is idle static inline int -async_request_is_idle(AsyncRequest *request) +async_request_is_idle(AsyncRequest* request) { return (request->state & ASYNC_REQUEST_IDLE_GROUP) != 0; } @@ -415,7 +417,7 @@ async_request_is_idle(AsyncRequest *request) /// \retval 1 The request has completed successfully. static inline int -async_request_completed(AsyncRequest *request) +async_request_completed(AsyncRequest* request) { return (request->state == ASYNC_REQUEST_STATE_COMPLETE); } @@ -431,7 +433,7 @@ async_request_latency(AsyncRequest* request, SsxTimebase* latency); void -async_request_printk(AsyncRequest *request); +async_request_printk(AsyncRequest* request); #endif /* __ASSEMBLER__ */ @@ -462,7 +464,8 @@ async_request_printk(AsyncRequest *request); /// high-priority jobs will run in the reverse order from which they were /// enqueued. -typedef struct AsyncQueue { +typedef struct AsyncQueue +{ /// The sentinel of the request queue SsxDeque deque; @@ -502,13 +505,13 @@ async_error_handler(AsyncQueue* queue, uint8_t completion_state); void async_edge_handler_setup(SsxIrqHandler handler, - void *arg, + void* arg, SsxIrqId irq, int priority); void async_level_handler_setup(SsxIrqHandler handler, - void *arg, + void* arg, SsxIrqId irq, int priority, int polarity); @@ -528,7 +531,8 @@ async_callbacks_initialize(SsxIrqId irq); struct GpeQueue; /// GPE FFDC -typedef struct { +typedef struct +{ uint32_t func_id; int32_t ipc_rc; int xir_dump_rc; @@ -546,7 +550,8 @@ typedef struct { /// e.g., to do ping-pong buffer management. None of the other fields should /// be directly modified by the application. -typedef struct { +typedef struct +{ /// The generic request AsyncRequest request; @@ -571,20 +576,20 @@ gpe_error_method(AsyncRequest* request); int gpe_request_create(GpeRequest* request, - struct GpeQueue* queue, - ipc_func_enum_t func_id, - void* cmd_data, - SsxInterval timeout, - AsyncRequestCallback callback, - void *arg, - int options); + struct GpeQueue* queue, + ipc_func_enum_t func_id, + void* cmd_data, + SsxInterval timeout, + AsyncRequestCallback callback, + void* arg, + int options); /// See async_request_schedule() for documentation. static inline int gpe_request_schedule(GpeRequest* request) { - return async_request_schedule((AsyncRequest *)request); + return async_request_schedule((AsyncRequest*)request); } //////////////////////////////////////////////////////////////////////////// @@ -597,7 +602,8 @@ gpe_request_schedule(GpeRequest* request) /// A GPE queue consists of a generic AsyncQueue to manage jobs on the /// engine. -typedef struct GpeQueue { +typedef struct GpeQueue +{ /// The generic request queue - the "base class" AsyncQueue queue; @@ -606,14 +612,14 @@ typedef struct GpeQueue { uint8_t ipc_target_id; /// Pointer to an IPC command message - ipc_async_cmd_t *ipc_cmd; + ipc_async_cmd_t* ipc_cmd; } GpeQueue; int -gpe_queue_create(GpeQueue *queue, - int engine); +gpe_queue_create(GpeQueue* queue, + int engine); #endif /* ASSEMBLER */ @@ -629,7 +635,8 @@ gpe_queue_create(GpeQueue *queue, /// structure are embedded in higher-level structures for the PBA bridge, BCE /// engines, and PBAX mechanism. -typedef struct { +typedef struct +{ /// FFDC from the PLB (OCI) arbiter OciFfdc oci_ffdc; @@ -674,7 +681,8 @@ typedef struct { /// direct bridge operations after OCC initialization. This structure extends /// the common PBA FFDC with information on how the slaves were programmed. -typedef struct { +typedef struct +{ /// Common FFDC PbaCommonFfdc common; @@ -694,7 +702,8 @@ typedef struct { /// Similar to the way the drivers are coded, the BCDE register forms are used /// to declare the structures. -typedef struct { +typedef struct +{ /// Common FFDC PbaCommonFfdc common; @@ -716,7 +725,8 @@ typedef struct { /// FFDC collected for PBAX send errors -typedef struct { +typedef struct +{ /// Common FFDC PbaCommonFfdc common; @@ -735,7 +745,8 @@ typedef struct { /// FFDC collected for PBAX receive errors -typedef struct { +typedef struct +{ /// Common FFDC PbaCommonFfdc common; @@ -757,7 +768,8 @@ typedef struct { /// A single global structure containing FFDC for all PBA functions -typedef struct { +typedef struct +{ /// FFDC for the generic bridge PbaBridgeFfdc bridge; @@ -770,10 +782,10 @@ typedef struct { /// FFDC for PBAX send PbaxSendFfdc pbax_send; - + /// FFDC for PBAX receive PbaxReceiveFfdc pbax_receive; - + } PbaUnitFfdc; #endif // __ASSEMBLER__ @@ -796,7 +808,8 @@ struct BceQueue; /// through the channel, the software layer allows any amount of data to be /// moved as a single request. -typedef struct { +typedef struct +{ /// The generic request AsyncRequest request; @@ -840,14 +853,14 @@ typedef struct { } BceRequest; int -bce_request_create(BceRequest *request, - struct BceQueue *queue, +bce_request_create(BceRequest* request, + struct BceQueue* queue, uint32_t bridge_address, uint32_t oci_address, size_t bytes, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options); #endif /* __ASSEMBLER__ */ @@ -874,7 +887,8 @@ bce_request_create(BceRequest *request, /// jobs on the engine and the PBA engine id. The BCDE and BCUE can use the /// same driver because their control interfaces are identical. -typedef struct BceQueue { +typedef struct BceQueue +{ /// The generic request queue AsyncQueue queue; @@ -886,12 +900,12 @@ typedef struct BceQueue { int -bce_queue_create(BceQueue *queue, +bce_queue_create(BceQueue* queue, int engine); int -bce_request_schedule(BceRequest *request); +bce_request_schedule(BceRequest* request); #endif /* __ASSEMBLER__ */ @@ -933,7 +947,8 @@ struct PbaxQueue; /// buffer size. For free-form communications an aggressive read protocol must /// be used. -typedef struct { +typedef struct +{ /// The generic request AsyncRequest request; @@ -942,7 +957,7 @@ typedef struct { /// /// This field is not modified by the drivers. The application may modify /// this field any time the PbaxRequest is idle. - uint64_t *data; + uint64_t* data; /// Number of bytes to move, which must be a multiple of 8. /// @@ -964,18 +979,18 @@ typedef struct { int -pbax_request_create(PbaxRequest *request, - struct PbaxQueue *queue, - uint64_t *data, +pbax_request_create(PbaxRequest* request, + struct PbaxQueue* queue, + uint64_t* data, size_t bytes, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options); int -pbax_request_schedule(PbaxRequest *request); +pbax_request_schedule(PbaxRequest* request); #endif /* __ASSEMBLER__ */ @@ -1004,7 +1019,8 @@ extern const SsxAddress pba_xshincn[]; /// A PBAX circular buffer queue consists of a generic AsyncQueue to manage /// jobs on the engine, a pointer to the data area and the PBAX engine id. -typedef struct PbaxQueue { +typedef struct PbaxQueue +{ /// The generic request queue AsyncQueue queue; @@ -1013,7 +1029,7 @@ typedef struct PbaxQueue { /// /// This data area must satisfy stringent alignment constraints; See the /// documentation for PbaxRequest. - uint64_t *cq_base; + uint64_t* cq_base; /// The number of 8-byte entries in the queue. /// @@ -1039,17 +1055,17 @@ typedef struct PbaxQueue { int -pbax_queue_create(PbaxQueue *queue, +pbax_queue_create(PbaxQueue* queue, int engine, - uint64_t *cq_base, + uint64_t* cq_base, size_t cq_entries, int protocol); int -pbax_queue_disable(PbaxQueue *queue); +pbax_queue_disable(PbaxQueue* queue); int -pbax_queue_enable(PbaxQueue *queue); +pbax_queue_enable(PbaxQueue* queue); int pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read); @@ -1069,7 +1085,7 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read); /// reasonably attributed to an OCB channel under the control of OCC, and 2) /// general errors signalled by the OCB direct bridge. Due to the myriad ways /// that OCB channels can be used the FFDC for OCB direct bridge errors is -/// stored globally rather than with particular requests or queues. +/// stored globally rather than with particular requests or queues. /// /// The OcbFfdc includes the PLB arbiter PEARL and PESR register state. /// This state is only collected if the error status indicates an OCI timeout @@ -1079,12 +1095,13 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read); /// then disable the channel since any further communication through the /// channel must be considered compromised. -typedef struct { +typedef struct +{ /// FFDC from the OCI (PLB) arbiter OciFfdc oci_ffdc; - /// A copy of the OCB OCC_LFIR register at the time of the error + /// A copy of the OCB OCC_LFIR register at the time of the error ocb_occlfir_t fir; /// A copy of the OCB Control/Status register for the channel at the time @@ -1127,7 +1144,8 @@ typedef struct { /// /// Contains FFDC structures for each channel and the direct bridge -typedef struct { +typedef struct +{ OcbFfdc channel[OCB_INDIRECT_CHANNELS]; OcbFfdc bridge; @@ -1178,14 +1196,15 @@ struct OcbQueue; /// partner has received the data, but simply that the data has been queued /// for reception and the caller may reuse/refill the data buffer if required. -typedef struct { +typedef struct +{ /// The generic request AsyncRequest request; /// Initial pointer to the data to be moved for write data, or the /// data area to hold read data. This field is not modified by the drivers. - uint64_t *data; + uint64_t* data; /// Number of bytes to move. This field is not modified by the drivers. size_t bytes; @@ -1201,18 +1220,18 @@ typedef struct { int -ocb_request_create(OcbRequest *request, - struct OcbQueue *queue, - uint64_t *data, +ocb_request_create(OcbRequest* request, + struct OcbQueue* queue, + uint64_t* data, size_t bytes, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options); int -ocb_request_schedule(OcbRequest *request); +ocb_request_schedule(OcbRequest* request); #endif /* __ASSEMBLER__ */ @@ -1225,7 +1244,7 @@ ocb_request_schedule(OcbRequest *request); // occhw_async.c - these constants are used as array indices. The code also // assumes this ordering for the access of G_ocb_ocbsesn[], and for // determining whether the engine is a PUSH or PULL queue. -// Note: push/pull queues for channel 3 have been deleted +// Note: push/pull queues for channel 3 have been deleted #define OCB_ENGINE_PUSH0 0 #define OCB_ENGINE_PULL0 1 @@ -1245,13 +1264,14 @@ ocb_request_schedule(OcbRequest *request); /// A OCB circular buffer queue consists of a generic AsyncQueue to manage /// jobs on the engine, a pointer to the data area and the OCB engine id. -typedef struct OcbQueue { +typedef struct OcbQueue +{ /// The generic request queue AsyncQueue queue; /// The base of the circular queue data area - must be 8-byte aligned - uint64_t *cq_base; + uint64_t* cq_base; /// The length of the queue in terms of the number of 8-byte entries in /// the queue. @@ -1272,9 +1292,9 @@ typedef struct OcbQueue { int -ocb_queue_create(OcbQueue *queue, +ocb_queue_create(OcbQueue* queue, int engine, - uint64_t *cq_base, + uint64_t* cq_base, size_t cq_length, int protocol); @@ -1476,7 +1496,7 @@ extern PbaxQueue G_pbax_read_queue[]; #define _PBAX_ALIGN_(length) \ (((length) <= 4) ? 32 : \ (((length) <= 8) ? 64 : \ - (((length) <= 16) ? 128 : 256))) + (((length) <= 16) ? 128 : 256))) #define PBAX_CQ_READ_BUFFER(buffer, length) \ uint64_t buffer[length] \ @@ -1490,20 +1510,20 @@ extern uint64_t G_pbax_read1_buffer[]; // Initialization APIs void -async_gpe_initialize(GpeQueue *queue, int engine); +async_gpe_initialize(GpeQueue* queue, int engine); void -async_bce_initialize(BceQueue *queue, int engine, SsxIrqId irq); +async_bce_initialize(BceQueue* queue, int engine, SsxIrqId irq); void -async_ocb_initialize(OcbQueue *queue, int engine, - uint64_t *buffer, size_t length, int protocol); +async_ocb_initialize(OcbQueue* queue, int engine, + uint64_t* buffer, size_t length, int protocol); void -async_pbax_initialize(PbaxQueue *queue, int engine, SsxIrqId irq, - uint64_t *buffer, size_t length, int protocol); +async_pbax_initialize(PbaxQueue* queue, int engine, SsxIrqId irq, + uint64_t* buffer, size_t length, int protocol); void diff --git a/src/ssx/occhw/occhw_async_gpe.c b/src/ssx/occhw/occhw_async_gpe.c index 524411d..b9835eb 100644 --- a/src/ssx/occhw/occhw_async_gpe.c +++ b/src/ssx/occhw/occhw_async_gpe.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -66,13 +66,14 @@ ipc_async_cmd_t G_async_ipc_cmd[ASYNC_NUM_GPE_QUEUES] SECTION_ATTRIBUTE(".noncac /// /// \retval -ASYNC_INVALID_OBJECT_PORE_QUEUE The \a queue was NULL (0). /// -/// \retval -ASYNC_INVALID_ENGINE_GPE The \a engine is not a (valid) +/// \retval -ASYNC_INVALID_ENGINE_GPE The \a engine is not a (valid) /// GPE engine. int -gpe_queue_create(GpeQueue *queue, int engine) +gpe_queue_create(GpeQueue* queue, int engine) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_GPE_QUEUE); SSX_ERROR_IF(!(engine & ASYNC_ENGINE_GPE), ASYNC_INVALID_ENGINE_GPE); SSX_ERROR_IF((ASYNC_ENG2GPE(engine) >= ASYNC_NUM_GPE_QUEUES), ASYNC_INVALID_ENGINE_GPE); @@ -105,14 +106,14 @@ gpe_async_handler(ipc_msg_t* rsp, void* arg) if(rsp->ipc_rc != IPC_RC_SUCCESS) { //calls gpe_error_method before calling async_handler - async_error_handler((AsyncQueue *)arg, ASYNC_REQUEST_STATE_FAILED); + async_error_handler((AsyncQueue*)arg, ASYNC_REQUEST_STATE_FAILED); } else { //handle async callbacks and process the next gpe request in the queue //(if any) - async_handler((AsyncQueue *) arg); + async_handler((AsyncQueue*) arg); } } @@ -149,7 +150,7 @@ gpe_async_handler(ipc_msg_t* rsp, void* arg) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_OBJECT_GPE_REQUEST The \a request was NULL (0) +/// \retval -ASYNC_INVALID_OBJECT_GPE_REQUEST The \a request was NULL (0) /// or the \a queue was NULL (0) or not a GpeQueue. /// /// \retval IPC_RC_INVALID_FUNC_ID The func_id has an invalid target id @@ -159,20 +160,21 @@ gpe_async_handler(ipc_msg_t* rsp, void* arg) /// call. int -gpe_request_create(GpeRequest *request, - GpeQueue *queue, +gpe_request_create(GpeRequest* request, + GpeQueue* queue, ipc_func_enum_t func_id, void* cmd_data, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options) { - AsyncQueue *async_queue = (AsyncQueue *)queue; + AsyncQueue* async_queue = (AsyncQueue*)queue; uint32_t targeted_func_id; int rc; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(!(async_queue->engine & ASYNC_ENGINE_GPE), ASYNC_INVALID_OBJECT_GPE_REQUEST); } @@ -186,6 +188,7 @@ gpe_request_create(GpeRequest *request, callback, arg, options); + if(!rc) { @@ -203,7 +206,7 @@ gpe_request_create(GpeRequest *request, //single target function IDs already have a target targeted_func_id = func_id; } - + //check that target id of the command matches the target id //of the queue. if (IPC_GET_TARGET_ID(targeted_func_id) != queue->ipc_target_id) @@ -230,13 +233,13 @@ gpe_request_create(GpeRequest *request, // // This routine sends an async_request to a GPE. // - + int -gpe_run_method(AsyncRequest *async_request) +gpe_run_method(AsyncRequest* async_request) { - GpeQueue *queue = (GpeQueue*)(async_request->queue); - GpeRequest *request = (GpeRequest*)async_request; - ipc_async_cmd_t *ipc_cmd = queue->ipc_cmd; + GpeQueue* queue = (GpeQueue*)(async_request->queue); + GpeRequest* request = (GpeRequest*)async_request; + ipc_async_cmd_t* ipc_cmd = queue->ipc_cmd; int rc; //Initialize the IPC command message @@ -277,21 +280,21 @@ gpe_run_method(AsyncRequest *async_request) int -gpe_error_method(AsyncRequest *async_request) +gpe_error_method(AsyncRequest* async_request) { - GpeQueue *queue = (GpeQueue*)(async_request->queue); - GpeRequest *request = (GpeRequest*)async_request; + GpeQueue* queue = (GpeQueue*)(async_request->queue); + GpeRequest* request = (GpeRequest*)async_request; // Collect data that could explain why a GPE command // couldn't be sent or timed out on the response and save it // in the ffdc fields - + //retrieve IPC data request->ffdc.func_id = queue->ipc_cmd->cmd.func_id.word32; request->ffdc.ipc_rc = queue->ipc_cmd->cmd.ipc_rc; - + //retrieve XIR data - request->ffdc.xir_dump_rc = + request->ffdc.xir_dump_rc = occhw_xir_dump(queue->ipc_target_id, &request->ffdc.xir_dump); return 0; @@ -303,7 +306,7 @@ gpe_error_method(AsyncRequest *async_request) //////////////////////////////////////////////////////////////////////////// void -async_gpe_initialize(GpeQueue *queue,int engine) +async_gpe_initialize(GpeQueue* queue, int engine) { gpe_queue_create(queue, engine); } diff --git a/src/ssx/occhw/occhw_async_ocb.c b/src/ssx/occhw/occhw_async_ocb.c index 1a0abef..9000c53 100644 --- a/src/ssx/occhw/occhw_async_ocb.c +++ b/src/ssx/occhw/occhw_async_ocb.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -45,16 +45,16 @@ OcbQueue G_ocb_write_queue[OCB_INDIRECT_CHANNELS]; #if OCB_READ0_LENGTH % CACHE_LINE_SIZE -#error "OCB read buffer 0 alignment error" + #error "OCB read buffer 0 alignment error" #endif #if OCB_READ1_LENGTH % CACHE_LINE_SIZE -#error "OCB read buffer 1 alignment error" + #error "OCB read buffer 1 alignment error" #endif #if OCB_READ2_LENGTH % CACHE_LINE_SIZE -#error "OCB read buffer 2 alignment error" + #error "OCB read buffer 2 alignment error" #endif #if OCB_READ3_LENGTH % CACHE_LINE_SIZE -#error "OCB read buffer 3 alignment error" + #error "OCB read buffer 3 alignment error" #endif // OCB circular queue write buffers must be 8-byte aligned per hardware @@ -94,33 +94,39 @@ OCB_CQ_WRITE_BUFFER(G_ocb_write3_buffer, OCB_WRITE3_LENGTH); /// OCB Stream Push/Pull Control/Status Register addresses static const SsxAddress G_ocb_ocbsxcsn[OCB_ENGINES] = - {OCB_OCBSHCS0, OCB_OCBSLCS0, - OCB_OCBSHCS1, OCB_OCBSLCS1, - OCB_OCBSHCS2, OCB_OCBSLCS2, - OCB_OCBSHCS3, OCB_OCBSLCS3}; +{ + OCB_OCBSHCS0, OCB_OCBSLCS0, + OCB_OCBSHCS1, OCB_OCBSLCS1, + OCB_OCBSHCS2, OCB_OCBSLCS2, + OCB_OCBSHCS3, OCB_OCBSLCS3 +}; /// OCB Stream Push/Pull Base Register addresses static const SsxAddress G_ocb_ocbsxbrn[OCB_ENGINES] = - {OCB_OCBSHBR0, OCB_OCBSLBR0, - OCB_OCBSHBR1, OCB_OCBSLBR1, - OCB_OCBSHBR2, OCB_OCBSLBR2, - OCB_OCBSHBR3, OCB_OCBSLBR3}; +{ + OCB_OCBSHBR0, OCB_OCBSLBR0, + OCB_OCBSHBR1, OCB_OCBSLBR1, + OCB_OCBSHBR2, OCB_OCBSLBR2, + OCB_OCBSHBR3, OCB_OCBSLBR3 +}; /// OCB Stream Push/Pull Increment Register addresses static const SsxAddress G_ocb_ocbsxin[OCB_ENGINES] = - {OCB_OCBSHI0, OCB_OCBSLI0, - OCB_OCBSHI1, OCB_OCBSLI1, - OCB_OCBSHI2, OCB_OCBSLI2, - OCB_OCBSHI3, OCB_OCBSLI3}; +{ + OCB_OCBSHI0, OCB_OCBSLI0, + OCB_OCBSHI1, OCB_OCBSLI1, + OCB_OCBSHI2, OCB_OCBSLI2, + OCB_OCBSHI3, OCB_OCBSLI3 +}; /// OCB Stream Error Status; There is only one register per OCB channel const SsxAddress G_ocb_ocbsesn[OCB_ENGINES / 2] = - {OCB_OCBSES0, OCB_OCBSES1, OCB_OCBSES2, OCB_OCBSES3}; +{OCB_OCBSES0, OCB_OCBSES1, OCB_OCBSES2, OCB_OCBSES3}; //////////////////////////////////////////////////////////////////////////// @@ -153,19 +159,26 @@ ocb_ffdc(int channel) ocb_ocbshcsn_t ocbshcsn; ocb_ocbslcsn_t ocbslcsn; - if (channel < 0) { + if (channel < 0) + { ffdc = &(G_ocb_ffdc.bridge); - } else { + } + else + { ffdc = &(G_ocb_ffdc.channel[channel]); } - if (ffdc->error == 0) { - - if (channel < 0) { + if (ffdc->error == 0) + { + + if (channel < 0) + { memset(ffdc, 0, sizeof(OcbFfdc)); - } else { + } + else + { getscom(OCB_OCBCSRN(channel), &(ffdc->csr.value)); @@ -199,7 +212,7 @@ ocb_ffdc(int channel) /// \param buf The caller's data buffer to receive the read data /// /// \param bytes The maximum number of bytes to read. This value must be an -/// even multiple of 8, as this API always reads multiples of 8 bytes. +/// even multiple of 8, as this API always reads multiples of 8 bytes. /// /// \param read The number of bytes actually copied from the device buffer to /// the caller's buffer. This may be returned as any value from 0 to \a @@ -209,7 +222,7 @@ ocb_ffdc(int channel) /// queue data area to the caller's data area, with the side effect of /// advancing the hardware queue pointers. ocb_read() does not implement /// locking, critical sections or any other type of synchronization for access -/// to the OCB queue data - that is the responsibility of the caller. +/// to the OCB queue data - that is the responsibility of the caller. /// /// ocb_read() may return an error code. This may indicate a preexisting /// error in the queue, or may be an error resulting from the current read. @@ -217,34 +230,37 @@ ocb_ffdc(int channel) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_OCB_READ The number of \a bytes is not +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_READ The number of \a bytes is not /// an even multiple of 8. /// -/// \retval -ASYNC_OCB_ERROR_READ_OLD or -ASYNC_OCB_ERROR_READ_NEW This code +/// \retval -ASYNC_OCB_ERROR_READ_OLD or -ASYNC_OCB_ERROR_READ_NEW This code /// indicates an error associated with the OCB channel represented by the queue. int -ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) +ocb_read(OcbQueue* queue, void* buf, size_t bytes, size_t* read) { ocb_ocbshcsn_t csr; ocb_ocbsesn_t ses; unsigned qlen, read_ptr, write_ptr, to_read; - uint64_t *pcq, *pbuf; + uint64_t* pcq, *pbuf; int rc; - do { + do + { rc = 0; *read = 0; // If pre-existing errors exist then immediately abort the read. - if (G_ocb_ffdc.channel[queue->engine / 2].error) { + if (G_ocb_ffdc.channel[queue->engine / 2].error) + { rc = -ASYNC_OCB_ERROR_READ_OLD; break; } - if (bytes % 8) { + if (bytes % 8) + { rc = -ASYNC_INVALID_ARGUMENT_OCB_READ; break; } @@ -262,17 +278,26 @@ ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) qlen = csr.fields.push_length + 1; read_ptr = csr.fields.push_read_ptr; - if (csr.fields.push_empty) { + if (csr.fields.push_empty) + { break; - } else if (csr.fields.push_full) { + } + else if (csr.fields.push_full) + { to_read = qlen; - } else { + } + else + { write_ptr = csr.fields.push_write_ptr; - if (read_ptr > write_ptr) { + + if (read_ptr > write_ptr) + { to_read = qlen - (read_ptr - write_ptr); - } else { + } + else + { to_read = write_ptr - read_ptr; } } @@ -288,12 +313,17 @@ ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) // copied from the queue. pbuf = (uint64_t*)buf; - while (bytes && to_read--) { + + while (bytes && to_read--) + { read_ptr++; - if (read_ptr == qlen) { + + if (read_ptr == qlen) + { read_ptr = 0; } + pcq = queue->cq_base + read_ptr; dcache_invalidate_line(pcq); @@ -303,12 +333,15 @@ ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) bytes -= 8; *read += 8; } - } while (0); + } + while (0); // Check for underflow errors. If found, collect FFDC. ses.value = in32(G_ocb_ocbsesn[queue->engine / 2]); - if (ses.fields.push_read_underflow) { + + if (ses.fields.push_read_underflow) + { ocb_ffdc(queue->engine / 2); rc = -ASYNC_OCB_ERROR_READ_NEW; } @@ -324,7 +357,7 @@ ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) /// \param buf The caller's data buffer containing the write data /// /// \param bytes The maximum number of bytes to write. This value must be an -/// even multiple of 8, as this API always writes multiples of 8 bytes. +/// even multiple of 8, as this API always writes multiples of 8 bytes. /// /// \param written The number of bytes actually copied from the caller's buffer to /// the device buffer. This may be returned as any value from 0 to \a @@ -342,34 +375,37 @@ ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_OCB_WRITE The number of \a bytes is not +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_WRITE The number of \a bytes is not /// an even multiple of 8. /// -/// \retval -ASYNC_OCB_ERROR_WRITE_OLD or -ASYNC_OCB_ERROR_WRITE_NEW This code +/// \retval -ASYNC_OCB_ERROR_WRITE_OLD or -ASYNC_OCB_ERROR_WRITE_NEW This code /// indicates an error associated with the OCB channel represented by the queue. int -ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written) +ocb_write(OcbQueue* queue, void* buf, size_t bytes, size_t* written) { ocb_ocbslcsn_t csr; ocb_ocbsesn_t ses; unsigned qlen, read_ptr, write_ptr, free; - uint64_t *pcq, *pbuf; + uint64_t* pcq, *pbuf; int rc; - do { + do + { rc = 0; *written = 0; // Pre-existing errors immediately abort the read. - if (G_ocb_ffdc.channel[queue->engine / 2].error) { + if (G_ocb_ffdc.channel[queue->engine / 2].error) + { rc = -ASYNC_OCB_ERROR_WRITE_OLD; break; } - if (bytes % 8) { + if (bytes % 8) + { rc = -ASYNC_INVALID_ARGUMENT_OCB_WRITE; break; } @@ -386,17 +422,25 @@ ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written) qlen = csr.fields.pull_length + 1; write_ptr = csr.fields.pull_write_ptr; - if (csr.fields.pull_full) { + if (csr.fields.pull_full) + { break; } - if (csr.fields.pull_empty) { + if (csr.fields.pull_empty) + { free = qlen; - } else { + } + else + { read_ptr = csr.fields.pull_read_ptr; - if (write_ptr > read_ptr) { + + if (write_ptr > read_ptr) + { free = qlen - (write_ptr - read_ptr); - } else { + } + else + { free = read_ptr - write_ptr; } } @@ -411,12 +455,17 @@ ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written) // copied into the queue. pbuf = (uint64_t*)buf; - while (bytes && free--) { + + while (bytes && free--) + { write_ptr++; - if (write_ptr == qlen) { + + if (write_ptr == qlen) + { write_ptr = 0; } + pcq = queue->cq_base + write_ptr; *pcq = *pbuf++; @@ -426,12 +475,15 @@ ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written) bytes -= 8; *written += 8; } - } while (0); + } + while (0); // Check for overflow. If found, collect FFDC. ses.value = in32(G_ocb_ocbsesn[queue->engine / 2]); - if (ses.fields.pull_write_overflow) { + + if (ses.fields.pull_write_overflow) + { ocb_ffdc(queue->engine / 2); rc = -ASYNC_OCB_ERROR_WRITE_NEW; } @@ -443,21 +495,25 @@ ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written) // This is the internal 'run method' for reading through an OCB circular // queue. The run method simply enables the IRQ. The interrupt handler reads // data from the queue and leaves the interrupt enabled until the read is -// satisfied. +// satisfied. static int -ocb_read_method(AsyncRequest *async_request) +ocb_read_method(AsyncRequest* async_request) { - OcbRequest *request = (OcbRequest*)async_request; - OcbQueue *queue = (OcbQueue*)(async_request->queue); + OcbRequest* request = (OcbRequest*)async_request; + OcbQueue* queue = (OcbQueue*)(async_request->queue); int rc; - if (request->bytes == 0) { + if (request->bytes == 0) + { rc = -ASYNC_REQUEST_COMPLETE; - } else { + } + else + { ssx_irq_enable(queue->irq); rc = 0; } + return rc; } @@ -468,18 +524,22 @@ ocb_read_method(AsyncRequest *async_request) // satisfied. static int -ocb_write_method(AsyncRequest *async_request) +ocb_write_method(AsyncRequest* async_request) { - OcbRequest *request = (OcbRequest *)async_request; - OcbQueue *queue = (OcbQueue*)(async_request->queue); + OcbRequest* request = (OcbRequest*)async_request; + OcbQueue* queue = (OcbQueue*)(async_request->queue); int rc; - if (request->bytes == 0) { + if (request->bytes == 0) + { rc = -ASYNC_REQUEST_COMPLETE; - } else { + } + else + { ssx_irq_enable(queue->irq); rc = 0; } + return rc; } @@ -490,13 +550,13 @@ ocb_write_method(AsyncRequest *async_request) // the request. static int -ocb_async_error_method(AsyncRequest *request) +ocb_async_error_method(AsyncRequest* request) { - OcbQueue *queue = (OcbQueue*)(request->queue); + OcbQueue* queue = (OcbQueue*)(request->queue); ocb_ffdc(queue->engine / 2); return -1; } - + /// Create a request for an OCB circular queue /// @@ -536,27 +596,28 @@ ocb_async_error_method(AsyncRequest *request) /// \retval -ASYNC_INVALID_OBJECT_OCB_REQUEST The \a request or \a queue were NULL (0), or /// the \a queue is not an initialized OcbQueue. /// -/// \retval -ASYNC_INVALID_ARGUMENT_OCB_REQUEST The \a data pointer is +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_REQUEST The \a data pointer is /// NULL (0), or the number of bytes is not a multiple of 8. /// /// See async_request_create() for other errors that may be returned by this /// call. int -ocb_request_create(OcbRequest *request, - OcbQueue *queue, - uint64_t *data, +ocb_request_create(OcbRequest* request, + OcbQueue* queue, + uint64_t* data, size_t bytes, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options) { int rc; AsyncRunMethod run_method = 0; // Make GCC Happy - AsyncQueue *async_queue = (AsyncQueue *)queue; + AsyncQueue* async_queue = (AsyncQueue*)queue; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((request == 0) || (queue == 0) || !(async_queue->engine & ASYNC_ENGINE_OCB), @@ -566,21 +627,22 @@ ocb_request_create(OcbRequest *request, ASYNC_INVALID_ARGUMENT_OCB_REQUEST); } - switch (async_queue->engine) { - - case ASYNC_ENGINE_OCB_PULL0: - case ASYNC_ENGINE_OCB_PULL1: - case ASYNC_ENGINE_OCB_PULL2: - case ASYNC_ENGINE_OCB_PULL3: - run_method = ocb_write_method; - break; - - case ASYNC_ENGINE_OCB_PUSH0: - case ASYNC_ENGINE_OCB_PUSH1: - case ASYNC_ENGINE_OCB_PUSH2: - case ASYNC_ENGINE_OCB_PUSH3: - run_method = ocb_read_method; - break; + switch (async_queue->engine) + { + + case ASYNC_ENGINE_OCB_PULL0: + case ASYNC_ENGINE_OCB_PULL1: + case ASYNC_ENGINE_OCB_PULL2: + case ASYNC_ENGINE_OCB_PULL3: + run_method = ocb_write_method; + break; + + case ASYNC_ENGINE_OCB_PUSH0: + case ASYNC_ENGINE_OCB_PUSH1: + case ASYNC_ENGINE_OCB_PUSH2: + case ASYNC_ENGINE_OCB_PUSH3: + run_method = ocb_read_method; + break; } rc = async_request_create(&(request->request), @@ -610,22 +672,23 @@ ocb_request_create(OcbRequest *request, /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE The number of \a bytes +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE The number of \a bytes /// currently requested is not a multiple of 8. /// /// See async_request_schedule() for documentation of other errors int -ocb_request_schedule(OcbRequest *request) +ocb_request_schedule(OcbRequest* request) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((request->bytes % 8), ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE); } request->current = request->data; request->remaining = request->bytes; - return async_request_schedule((AsyncRequest *)request); + return async_request_schedule((AsyncRequest*)request); } @@ -650,7 +713,7 @@ ocb_request_schedule(OcbRequest *request) /// buffer. The base register is also set up. void -ocb_read_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) +ocb_read_engine_reset(OcbQueue* queue, size_t cq_length, int protocol) { ocb_ocbshcsn_t cs; @@ -673,9 +736,12 @@ ocb_read_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) // Reprogram and reenable/reset the queue - if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) { + if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) + { cs.fields.push_intr_action = OCB_INTR_ACTION_FULL; - } else { + } + else + { cs.fields.push_intr_action = OCB_INTR_ACTION_NOT_EMPTY; } @@ -703,7 +769,7 @@ ocb_read_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) /// buffer. The base register is also set up. void -ocb_write_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) +ocb_write_engine_reset(OcbQueue* queue, size_t cq_length, int protocol) { ocb_ocbslcsn_t cs; @@ -726,9 +792,12 @@ ocb_write_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) // Reprogram and reenable/reset the queue - if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) { + if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) + { cs.fields.pull_intr_action = OCB_INTR_ACTION_EMPTY; - } else { + } + else + { cs.fields.pull_intr_action = OCB_INTR_ACTION_NOT_FULL; } @@ -765,7 +834,7 @@ ocb_write_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) /// /// \retval -ASYNC_INVALID_OBJECT_OCB_QUEUE The \a queue was NULL (0). /// -/// \retval -ASYNC_INVALID_ARGUMENT_OCB_QUEUE The \a cq_base is not properly +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_QUEUE The \a cq_base is not properly /// aligned, or the \a cq_length is invalid, or the \a protocol is invalid. /// /// \retval -ASYNC_INVALID_ENGINE_OCB The \a engine is not an OCB engine. @@ -773,16 +842,17 @@ ocb_write_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) /// Other errors may be returned by async_queue_create(). int -ocb_queue_create(OcbQueue *queue, +ocb_queue_create(OcbQueue* queue, int engine, - uint64_t *cq_base, + uint64_t* cq_base, size_t cq_length, int protocol) { - AsyncQueue *async_queue = (AsyncQueue *)queue; + AsyncQueue* async_queue = (AsyncQueue*)queue; int align_mask = 0; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_OCB_QUEUE); SSX_ERROR_IF((cq_length < OCB_PUSH_PULL_LENGTH_MIN) || (cq_length > OCB_PUSH_PULL_LENGTH_MAX) || @@ -794,72 +864,75 @@ ocb_queue_create(OcbQueue *queue, queue->cq_base = cq_base; queue->cq_length = cq_length; - switch (engine) { + switch (engine) + { // These are the read engines from OCC's perspective. - case ASYNC_ENGINE_OCB_PUSH0: - queue->irq = OCCHW_IRQ_STRM0_PUSH; - queue->engine = OCB_ENGINE_PUSH0; - goto read_engine; - - case ASYNC_ENGINE_OCB_PUSH1: - queue->irq = OCCHW_IRQ_STRM1_PUSH; - queue->engine = OCB_ENGINE_PUSH1; - goto read_engine; - - case ASYNC_ENGINE_OCB_PUSH2: - queue->irq = OCCHW_IRQ_STRM2_PUSH; - queue->engine = OCB_ENGINE_PUSH2; - goto read_engine; - - case ASYNC_ENGINE_OCB_PUSH3: - queue->irq = OCCHW_IRQ_STRM3_PUSH; - queue->engine = OCB_ENGINE_PUSH3; - goto read_engine; - - read_engine: - align_mask = CACHE_LINE_SIZE - 1; - async_queue_create(async_queue, engine); - ocb_read_engine_reset(queue, cq_length, protocol); - break; + case ASYNC_ENGINE_OCB_PUSH0: + queue->irq = OCCHW_IRQ_STRM0_PUSH; + queue->engine = OCB_ENGINE_PUSH0; + goto read_engine; + + case ASYNC_ENGINE_OCB_PUSH1: + queue->irq = OCCHW_IRQ_STRM1_PUSH; + queue->engine = OCB_ENGINE_PUSH1; + goto read_engine; + + case ASYNC_ENGINE_OCB_PUSH2: + queue->irq = OCCHW_IRQ_STRM2_PUSH; + queue->engine = OCB_ENGINE_PUSH2; + goto read_engine; + + case ASYNC_ENGINE_OCB_PUSH3: + queue->irq = OCCHW_IRQ_STRM3_PUSH; + queue->engine = OCB_ENGINE_PUSH3; + goto read_engine; + + read_engine: + align_mask = CACHE_LINE_SIZE - 1; + async_queue_create(async_queue, engine); + ocb_read_engine_reset(queue, cq_length, protocol); + break; // These are the write engines from OCC's perspective. - case ASYNC_ENGINE_OCB_PULL0: - queue->irq = OCCHW_IRQ_STRM0_PULL; - queue->engine = OCB_ENGINE_PULL0; - goto write_engine; - - case ASYNC_ENGINE_OCB_PULL1: - queue->irq = OCCHW_IRQ_STRM1_PULL; - queue->engine = OCB_ENGINE_PULL1; - goto write_engine; - - case ASYNC_ENGINE_OCB_PULL2: - queue->irq = OCCHW_IRQ_STRM2_PULL; - queue->engine = OCB_ENGINE_PULL2; - goto write_engine; - - case ASYNC_ENGINE_OCB_PULL3: - queue->irq = OCCHW_IRQ_STRM3_PULL; - queue->engine = OCB_ENGINE_PULL3; - goto write_engine; - - write_engine: - align_mask = 8 - 1; - async_queue_create(async_queue, engine); - ocb_write_engine_reset(queue, cq_length, protocol); - break; - - default: - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_OCB); - } + case ASYNC_ENGINE_OCB_PULL0: + queue->irq = OCCHW_IRQ_STRM0_PULL; + queue->engine = OCB_ENGINE_PULL0; + goto write_engine; + + case ASYNC_ENGINE_OCB_PULL1: + queue->irq = OCCHW_IRQ_STRM1_PULL; + queue->engine = OCB_ENGINE_PULL1; + goto write_engine; + + case ASYNC_ENGINE_OCB_PULL2: + queue->irq = OCCHW_IRQ_STRM2_PULL; + queue->engine = OCB_ENGINE_PULL2; + goto write_engine; + + case ASYNC_ENGINE_OCB_PULL3: + queue->irq = OCCHW_IRQ_STRM3_PULL; + queue->engine = OCB_ENGINE_PULL3; + goto write_engine; + + write_engine: + align_mask = 8 - 1; + async_queue_create(async_queue, engine); + ocb_write_engine_reset(queue, cq_length, protocol); + break; + + default: + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_OCB); + } } - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF(((uint32_t)cq_base & align_mask) != 0, + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF(((uint32_t)cq_base & align_mask) != 0, ASYNC_INVALID_ARGUMENT_OCB_QUEUE2); } @@ -883,35 +956,44 @@ ocb_queue_create(OcbQueue *queue, SSX_IRQ_FAST2FULL(ocb_async_handler, ocb_async_handler_full); void -ocb_async_handler_full(void *arg, SsxIrqId irq, int priority) +ocb_async_handler_full(void* arg, SsxIrqId irq, int priority) { - AsyncQueue *async_queue = (AsyncQueue*)arg; - OcbQueue *queue = (OcbQueue*)async_queue; - OcbRequest *request = (OcbRequest*)(async_queue->current); + AsyncQueue* async_queue = (AsyncQueue*)arg; + OcbQueue* queue = (OcbQueue*)async_queue; + OcbRequest* request = (OcbRequest*)(async_queue->current); size_t processed; int rc; - if (SSX_ERROR_CHECK_KERNEL && (request == 0)) { + if (SSX_ERROR_CHECK_KERNEL && (request == 0)) + { SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_OCB); } - if (queue->engine % 2) { + if (queue->engine % 2) + { rc = ocb_write(queue, request->current, request->remaining, &processed); - } else { + } + else + { rc = ocb_read(queue, request->current, request->remaining, &processed); } - if (rc) { + if (rc) + { ssx_irq_disable(queue->irq); async_error_handler(async_queue, ASYNC_REQUEST_STATE_FAILED); - } else if (processed == request->remaining) { + } + else if (processed == request->remaining) + { ssx_irq_disable(queue->irq); async_handler(async_queue); - } else { + } + else + { request->current += (processed / 8); request->remaining -= processed; @@ -938,7 +1020,7 @@ ocb_async_handler_full(void *arg, SsxIrqId irq, int priority) SSX_IRQ_FAST2FULL(ocb_error_handler, ocb_error_handler_full); void -ocb_error_handler_full(void *arg, SsxIrqId irq, int priority) +ocb_error_handler_full(void* arg, SsxIrqId irq, int priority) { ocb_occlfir_t fir; ocb_occlfir_t fir_temp; @@ -948,23 +1030,34 @@ ocb_error_handler_full(void *arg, SsxIrqId irq, int priority) ssx_irq_status_clear(irq); getscom(OCB_OCCLFIR, &(fir.value)); - + fir_temp.value = 0; - fir_temp.fields.ocb_idc0_error = 1; - for (channel = 0; channel < OCB_INDIRECT_CHANNELS; channel++) { - if (fir.value & (fir_temp.value >> channel)) { + fir_temp.fields.ocb_idc0_error = 1; + + for (channel = 0; channel < OCB_INDIRECT_CHANNELS; channel++) + { + if (fir.value & (fir_temp.value >> channel)) + { queue = (AsyncQueue*)(&(G_ocb_read_queue[channel])); - if (queue->state == ASYNC_QUEUE_STATE_RUNNING) { + + if (queue->state == ASYNC_QUEUE_STATE_RUNNING) + { async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); - } else { + } + else + { ocb_ffdc(channel); } - + queue = (AsyncQueue*)(&(G_ocb_write_queue[channel])); - if (queue->state == ASYNC_QUEUE_STATE_RUNNING) { + + if (queue->state == ASYNC_QUEUE_STATE_RUNNING) + { async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); - } else { + } + else + { ocb_ffdc(channel); } } @@ -974,7 +1067,8 @@ ocb_error_handler_full(void *arg, SsxIrqId irq, int priority) fir.fields.ocb_db_oci_read_data_parity | fir.fields.ocb_db_oci_slave_error | fir.fields.ocb_pib_addr_parity_err | - fir.fields.ocb_db_pib_data_parity_err) { + fir.fields.ocb_db_pib_data_parity_err) + { ocb_ffdc(-1); } @@ -986,12 +1080,12 @@ ocb_error_handler_full(void *arg, SsxIrqId irq, int priority) //////////////////////////////////////////////////////////////////////////// void -async_ocb_initialize(OcbQueue *queue, int engine, - uint64_t *buffer, size_t length, int protocol) +async_ocb_initialize(OcbQueue* queue, int engine, + uint64_t* buffer, size_t length, int protocol) { ocb_queue_create(queue, engine, buffer, length, protocol); async_level_handler_setup(ocb_async_handler, - (void *)queue, + (void*)queue, queue->irq, SSX_NONCRITICAL, SSX_IRQ_POLARITY_ACTIVE_HIGH); diff --git a/src/ssx/occhw/occhw_async_pba.c b/src/ssx/occhw/occhw_async_pba.c index b4bc8fb..0ce0c27 100644 --- a/src/ssx/occhw/occhw_async_pba.c +++ b/src/ssx/occhw/occhw_async_pba.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -67,35 +67,35 @@ PBAX_CQ_READ_BUFFER(G_pbax_read1_buffer, PBAX_READ1_LENGTH); /// PBA BCDE/BCUE PowerBus BAR[0..31] static const SsxAddress G_bce_pbadr[BCE_ENGINES] = - {PBA_BCDE_PBADR, PBA_BCUE_PBADR}; +{PBA_BCDE_PBADR, PBA_BCUE_PBADR}; /// PBA BCDE/BCUE OCI BAR static const SsxAddress G_bce_ocibar[BCE_ENGINES] = - {PBA_BCDE_OCIBAR, PBA_BCUE_OCIBAR}; +{PBA_BCDE_OCIBAR, PBA_BCUE_OCIBAR}; /// PBA BCDE/BCUE SET register static const SsxAddress G_bce_set[BCE_ENGINES] = - {PBA_BCDE_SET, PBA_BCUE_SET}; +{PBA_BCDE_SET, PBA_BCUE_SET}; /// PBA BCDE/BCUE Control register static const SsxAddress G_bce_ctl[BCE_ENGINES] = - {PBA_BCDE_CTL, PBA_BCUE_CTL}; +{PBA_BCDE_CTL, PBA_BCUE_CTL}; /// PBA BCDE/BCUE Status register static const SsxAddress G_bce_stat[BCE_ENGINES] = - {PBA_BCDE_STAT, PBA_BCUE_STAT}; +{PBA_BCDE_STAT, PBA_BCUE_STAT}; /// PBAX Push Queue Control/Status Register addresses static const SsxAddress G_pba_xshcsn[PBAX_ENGINES] = - {PBA_XSHCS0, PBA_XSHCS1}; +{PBA_XSHCS0, PBA_XSHCS1}; /// PBAX Push Queue Base Register addresses static const SsxAddress G_pba_xshbrn[PBAX_ENGINES] = - {PBA_XSHBR0, PBA_XSHBR1}; +{PBA_XSHBR0, PBA_XSHBR1}; /// PBAX Push Queue Increment Register addresses static const SsxAddress G_pba_xshincn[PBAX_ENGINES] = - {PBA_XSHINC0, PBA_XSHINC1}; +{PBA_XSHINC0, PBA_XSHINC1}; //////////////////////////////////////////////////////////////////////////// @@ -120,21 +120,25 @@ pba_common_ffdc(PbaCommonFfdc* ffdc) { int i; - if (ffdc->error == 0) { + if (ffdc->error == 0) + { oci_ffdc(&(ffdc->oci_ffdc), OCI_MASTER_ID_PBA); ffdc->mode.value = in64(PBA_MODE); - - for (i = 0; i < PBA_READ_BUFFERS; i++) { + + for (i = 0; i < PBA_READ_BUFFERS; i++) + { getscom(PBA_RBUFVALN(i), &(ffdc->rbufval[i].value)); } - for (i = 0; i < PBA_WRITE_BUFFERS; i++) { + for (i = 0; i < PBA_WRITE_BUFFERS; i++) + { getscom(PBA_WBUFVALN(i), &(ffdc->wbufval[i].value)); } - for (i = 0; i < PBA_BARS; i++) { + for (i = 0; i < PBA_BARS; i++) + { getscom(PBA_BARN(i), &(ffdc->bar[i].value)); getscom(PBA_BARMSKN(i), &(ffdc->barmsk[i].value)); } @@ -159,13 +163,15 @@ pba_bridge_ffdc(PbaBridgeFfdc* ffdc) { int i; - if (ffdc->common.error == 0) { + if (ffdc->common.error == 0) + { pba_common_ffdc(&(ffdc->common)); ffdc->slvrst.value = in64(PBA_SLVRST); - for (i = 0; i > PBA_SLAVES; i++) { + for (i = 0; i > PBA_SLAVES; i++) + { ffdc->slvctl[i].value = in64(PBA_SLVCTLN(i)); } } @@ -179,7 +185,8 @@ pba_bridge_ffdc(PbaBridgeFfdc* ffdc) static void bce_ffdc(BceFfdc* ffdc, int engine) { - if (ffdc->common.error == 0) { + if (ffdc->common.error == 0) + { pba_common_ffdc(&(ffdc->common)); @@ -196,10 +203,11 @@ bce_ffdc(BceFfdc* ffdc, int engine) static void pbax_send_ffdc(PbaxSendFfdc* ffdc) { - if (ffdc->common.error == 0) { + if (ffdc->common.error == 0) + { pba_common_ffdc(&(ffdc->common)); - + ffdc->xcfg.value = in64(PBA_XCFG); ffdc->xsndtx.value = in64(PBA_XSNDTX); ffdc->xsndstat.value = in64(PBA_XSNDSTAT); @@ -217,14 +225,16 @@ pbax_receive_ffdc(PbaxReceiveFfdc* ffdc) { int i; - if (ffdc->common.error == 0) { + if (ffdc->common.error == 0) + { pba_common_ffdc(&(ffdc->common)); - + ffdc->xcfg.value = in64(PBA_XCFG); ffdc->xrcvstat.value = in64(PBA_XRCVSTAT); - - for (i = 0; i < PBAX_ENGINES; i++) { + + for (i = 0; i < PBAX_ENGINES; i++) + { ffdc->xshbrn[i].value = in64(PBA_XSHBRN(i)); ffdc->xshcsn[i].value = in64(PBA_XSHCSN(i)); } @@ -262,10 +272,10 @@ pbax_receive_ffdc(PbaxReceiveFfdc* ffdc) // register layout structures, but they work for BCUE as well. static int -bce_async_run_method(AsyncRequest *async_request) +bce_async_run_method(AsyncRequest* async_request) { - BceQueue *queue = (BceQueue *)(async_request->queue); - BceRequest *request = (BceRequest *)async_request; + BceQueue* queue = (BceQueue*)(async_request->queue); + BceRequest* request = (BceRequest*)async_request; int rc, engine; pba_bcde_pbadr_t pbadr; pba_bcde_set_t set; @@ -273,11 +283,14 @@ bce_async_run_method(AsyncRequest *async_request) size_t to_write; - if (request->remaining == 0) { + if (request->remaining == 0) + { rc = -ASYNC_REQUEST_COMPLETE; - } else { + } + else + { to_write = MIN(request->remaining, PBA_BCE_SIZE_MAX); @@ -314,7 +327,9 @@ bce_async_run_method(AsyncRequest *async_request) // Update the work remaining to be done. request->remaining -= to_write; - if (request->remaining != 0) { + + if (request->remaining != 0) + { request->next_bridge_address += to_write; request->next_oci_address += to_write; } @@ -333,19 +348,22 @@ bce_async_run_method(AsyncRequest *async_request) // whether to restart the queue. static int -bce_async_error_method(AsyncRequest *request) +bce_async_error_method(AsyncRequest* request) { - BceQueue *queue = (BceQueue*)(request->queue); + BceQueue* queue = (BceQueue*)(request->queue); int engine = queue->engine; - if (engine == BCE_ENGINE_BCDE) { + if (engine == BCE_ENGINE_BCDE) + { - bce_ffdc(&(G_pba_ffdc.bcde), engine); + bce_ffdc(&(G_pba_ffdc.bcde), engine); out32(PBA_BCDE_CTL, PBA_BCDE_CTL_STOP >> 32); - } else { + } + else + { - bce_ffdc(&(G_pba_ffdc.bcue), engine); + bce_ffdc(&(G_pba_ffdc.bcue), engine); out32(PBA_BCUE_CTL, PBA_BCUE_CTL_STOP >> 32); } @@ -396,28 +414,29 @@ bce_async_error_method(AsyncRequest *request) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_OBJECT_BCE_REQUEST The \a request was NULL (0), +/// \retval -ASYNC_INVALID_OBJECT_BCE_REQUEST The \a request was NULL (0), /// or the \a queue was NULL (0) or not a BceQueue. /// /// See async_request_create() for other errors that may be returned by this /// call. int -bce_request_create(BceRequest *request, - BceQueue *queue, +bce_request_create(BceRequest* request, + BceQueue* queue, uint32_t bridge_address, uint32_t oci_address, size_t bytes, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options) { int rc; - AsyncQueue *async_queue = (AsyncQueue *)queue; + AsyncQueue* async_queue = (AsyncQueue*)queue; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((request == 0) || (queue == 0) || !(async_queue->engine & ASYNC_ENGINE_BCE), @@ -463,30 +482,34 @@ bce_request_create(BceRequest *request, /// \retval -ASYNC_INVALID_ENGINE_BCE The \a engine is not a PBA engine. int -bce_queue_create(BceQueue *queue, +bce_queue_create(BceQueue* queue, int engine) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_BCE_QUEUE); } - switch (engine) { + switch (engine) + { - case ASYNC_ENGINE_BCDE: - async_queue_create(&(queue->queue), engine); - queue->engine = BCE_ENGINE_BCDE; - break; + case ASYNC_ENGINE_BCDE: + async_queue_create(&(queue->queue), engine); + queue->engine = BCE_ENGINE_BCDE; + break; - case ASYNC_ENGINE_BCUE: - async_queue_create(&(queue->queue), engine); - queue->engine = BCE_ENGINE_BCUE; - break; + case ASYNC_ENGINE_BCUE: + async_queue_create(&(queue->queue), engine); + queue->engine = BCE_ENGINE_BCUE; + break; - default: - if (SSX_ERROR_CHECK_API) { - SSX_ERROR(ASYNC_INVALID_ENGINE_BCE); - } - break; + default: + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR(ASYNC_INVALID_ENGINE_BCE); + } + + break; } return 0; @@ -502,16 +525,17 @@ bce_queue_create(BceQueue *queue, /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_BCE_SCHEDULE Either the \a bridge_address +/// \retval -ASYNC_INVALID_ARGUMENT_BCE_SCHEDULE Either the \a bridge_address /// is not 128-byte aligned, or the OCI address is not 128-byte aligned, or the /// number of bytes is not a multiple of 128. /// /// See async_request_schedule() for documentation of other errors int -bce_request_schedule(BceRequest *request) +bce_request_schedule(BceRequest* request) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((request->bridge_address % POWERBUS_CACHE_LINE_SIZE) || (request->oci_address % POWERBUS_CACHE_LINE_SIZE) || (request->bytes % POWERBUS_CACHE_LINE_SIZE), @@ -522,7 +546,7 @@ bce_request_schedule(BceRequest *request) request->next_oci_address = request->oci_address; request->remaining = request->bytes; - return async_request_schedule((AsyncRequest *)request); + return async_request_schedule((AsyncRequest*)request); } @@ -538,19 +562,21 @@ bce_request_schedule(BceRequest *request) SSX_IRQ_FAST2FULL(bce_async_handler, bce_async_handler_full); void -bce_async_handler_full(void *arg, SsxIrqId irq, int priority) +bce_async_handler_full(void* arg, SsxIrqId irq, int priority) { - AsyncQueue *async_queue = (AsyncQueue *)arg; - AsyncRequest *async_current = (AsyncRequest *)async_queue->current; - BceQueue *queue = (BceQueue *)async_queue; + AsyncQueue* async_queue = (AsyncQueue*)arg; + AsyncRequest* async_current = (AsyncRequest*)async_queue->current; + BceQueue* queue = (BceQueue*)async_queue; out32(G_bce_ctl[queue->engine], 0); - if (SSX_ERROR_CHECK_KERNEL && (async_current == 0)) { + if (SSX_ERROR_CHECK_KERNEL && (async_current == 0)) + { SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_BCE); } - if (async_current->run_method(async_current) == -ASYNC_REQUEST_COMPLETE) { + if (async_current->run_method(async_current) == -ASYNC_REQUEST_COMPLETE) + { async_handler(async_queue); } } @@ -577,10 +603,10 @@ bce_async_handler_full(void *arg, SsxIrqId irq, int priority) /// queue data area to the caller's data area, with the side effect of /// advancing the hardware queue pointers. pbax_read() does not implement /// locking, critical sections or any other type of synchronization for access -/// to the PBAX queue data. +/// to the PBAX queue data. /// -/// pbax_read() returns the error code -ASYNC_PBAX_ERROR_OLD or -/// -ASYNC_PBAX_ERROR_NEW if PBAX receive error status is asserted. +/// pbax_read() returns the error code -ASYNC_PBAX_ERROR_OLD or +/// -ASYNC_PBAX_ERROR_NEW if PBAX receive error status is asserted. /// The error return code may be disjoint from the actual /// read: If data is available it may be copied to the caller's buffer, but /// this data should always be considered corrupted in the event of an error @@ -588,7 +614,7 @@ bce_async_handler_full(void *arg, SsxIrqId irq, int priority) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_READ The number of \a bytes is not +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_READ The number of \a bytes is not /// an even multiple of 8. /// /// \retval -ASYNC_PBAX_ERROR_OLD The PBA shows pre-existing error status @@ -605,10 +631,11 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read) pba_xshcsn_t csr; pba_xrcvstat_t rsr; unsigned qlen, read_ptr, write_ptr, to_read; - uint64_t *pcq, *pbuf; + uint64_t* pcq, *pbuf; int rc; - do { + do + { rc = 0; *read = 0; @@ -616,13 +643,16 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read) // If pre-existing errors exist then immediately abort the read. rsr.words.high_order = in32(PBA_XRCVSTAT); - if (rsr.fields.rcv_error) { + + if (rsr.fields.rcv_error) + { pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive)); rc = -ASYNC_PBAX_ERROR_OLD; break; } - if (bytes % 8) { + if (bytes % 8) + { rc = -ASYNC_INVALID_ARGUMENT_PBAX_READ; break; } @@ -639,17 +669,26 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read) qlen = csr.fields.push_length + 1; read_ptr = csr.fields.push_read_ptr; - if (csr.fields.push_empty) { + if (csr.fields.push_empty) + { break; - } else if (csr.fields.push_full) { + } + else if (csr.fields.push_full) + { to_read = qlen; - } else { + } + else + { write_ptr = csr.fields.push_write_ptr; - if (read_ptr > write_ptr) { + + if (read_ptr > write_ptr) + { to_read = qlen - (read_ptr - write_ptr); - } else { + } + else + { to_read = write_ptr - read_ptr; } } @@ -664,27 +703,35 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read) // copied from the queue. pbuf = (uint64_t*) buf; - while (bytes && to_read--) { + + while (bytes && to_read--) + { read_ptr++; - if (read_ptr == qlen) { + + if (read_ptr == qlen) + { read_ptr = 0; } + pcq = queue->cq_base + read_ptr; dcache_invalidate_line(pcq); *pbuf++ = *pcq; - out32(G_pba_xshincn[queue->engine], 0); + out32(G_pba_xshincn[queue->engine], 0); bytes -= 8; *read += 8; } - } while(0); + } + while(0); // Check for errors that occurred during the read rsr.words.high_order = in32(PBA_XRCVSTAT); - if (rsr.fields.rcv_error) { + + if (rsr.fields.rcv_error) + { pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive)); rc = -ASYNC_PBAX_ERROR_NEW; } @@ -699,18 +746,22 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read) // satisfied. int -pbax_read_method(AsyncRequest *async_request) +pbax_read_method(AsyncRequest* async_request) { - PbaxRequest *request = (PbaxRequest*)async_request; - PbaxQueue *queue = (PbaxQueue*)(async_request->queue); + PbaxRequest* request = (PbaxRequest*)async_request; + PbaxQueue* queue = (PbaxQueue*)(async_request->queue); int rc; - if (request->bytes == 0) { + if (request->bytes == 0) + { rc = -ASYNC_REQUEST_COMPLETE; - } else { + } + else + { ssx_irq_enable(queue->irq); rc = 0; } + return rc; } @@ -720,12 +771,12 @@ pbax_read_method(AsyncRequest *async_request) // Collect FFDC. static int -pbax_async_error_method(AsyncRequest *request) +pbax_async_error_method(AsyncRequest* request) { pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive)); return -1; } - + /// Create a request for a PBAX read queue /// @@ -761,10 +812,10 @@ pbax_async_error_method(AsyncRequest *request) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_OBJECT_PBAX_REQUEST The \a request or \a queue +/// \retval -ASYNC_INVALID_OBJECT_PBAX_REQUEST The \a request or \a queue /// were NULL (0), or the \a queue is not an initialized PbaxQueue. /// -/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_REQUEST The \a data pointer is +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_REQUEST The \a data pointer is /// NULL (0), or the number of bytes is not a multiple of 8. /// /// See async_request_create() for other errors that may be returned by this @@ -783,7 +834,8 @@ pbax_request_create(PbaxRequest* request, int rc; AsyncQueue* async_queue = (AsyncQueue*)queue; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((request == 0) || (queue == 0) || !(async_queue->engine & ASYNC_ENGINE_PBAX), @@ -817,22 +869,23 @@ pbax_request_create(PbaxRequest* request, /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE The number of \a bytes +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE The number of \a bytes /// currently requested is not a multiple of 8. /// /// See async_request_schedule() for documentation of other errors int -pbax_request_schedule(PbaxRequest *request) +pbax_request_schedule(PbaxRequest* request) { - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((request->bytes % 8),ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE); + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((request->bytes % 8), ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE); } request->current = request->data; request->remaining = request->bytes; - return async_request_schedule((AsyncRequest *)request); + return async_request_schedule((AsyncRequest*)request); } @@ -846,19 +899,20 @@ pbax_request_schedule(PbaxRequest *request) /// /// Disable the PBAX recieve mechanism for a particular PBAX receive queue. /// Interrupts are disabled, and any data managed by the queue is effectively -/// lost. +/// lost. /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0) -/// or otherwise invalid. +/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0) +/// or otherwise invalid. int -pbax_queue_disable(PbaxQueue *queue) +pbax_queue_disable(PbaxQueue* queue) { pba_xshcsn_t cs; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PBAX_DISABLE); } @@ -882,18 +936,19 @@ pbax_queue_disable(PbaxQueue *queue) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0) -/// or otherwise invalid. +/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0) +/// or otherwise invalid. int -pbax_queue_enable(PbaxQueue *queue) +pbax_queue_enable(PbaxQueue* queue) { int rc; pba_xshcsn_t cs; rc = pbax_queue_disable(queue); - if (!rc) { + if (!rc) + { // Reinitialize the data buffer base address register and // reprogram/re-enable the queue. @@ -902,9 +957,12 @@ pbax_queue_enable(PbaxQueue *queue) cs.value = 0; - if (queue->protocol == PBAX_INTERRUPT_PROTOCOL_LAZY) { + if (queue->protocol == PBAX_INTERRUPT_PROTOCOL_LAZY) + { cs.fields.push_intr_action = PBAX_INTR_ACTION_FULL; - } else { + } + else + { cs.fields.push_intr_action = PBAX_INTR_ACTION_NOT_EMPTY; } @@ -913,6 +971,7 @@ pbax_queue_enable(PbaxQueue *queue) out32(G_pba_xshcsn[queue->engine], cs.words.high_order); } + return 0; } @@ -944,7 +1003,7 @@ pbax_queue_enable(PbaxQueue *queue) /// /// \retval -ASYNC_INVALID_OBJECT_PBAX_QUEUE The \a queue was NULL (0). /// -/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_QUEUE The \a cq_base is not properly +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_QUEUE The \a cq_base is not properly /// aligned, or the \a cq_length is invalid, or the \a protocol is invalid. /// /// \retval -ASYNC_INVALID_ENGINE_PBAX The \a engine is not an PBAX engine. @@ -952,18 +1011,19 @@ pbax_queue_enable(PbaxQueue *queue) /// Other errors may be returned by async_queue_create(). int -pbax_queue_create(PbaxQueue *queue, +pbax_queue_create(PbaxQueue* queue, int engine, - uint64_t *cq_base, + uint64_t* cq_base, size_t cq_entries, int protocol) { - AsyncQueue *async_queue = (AsyncQueue *)queue; + AsyncQueue* async_queue = (AsyncQueue*)queue; - if (SSX_ERROR_CHECK_API) { - uint32_t align_mask = - POW2_32(MAX(CEILING_LOG2(cq_entries * 8), - LOG_CACHE_LINE_SIZE)) - 1; + if (SSX_ERROR_CHECK_API) + { + uint32_t align_mask = + POW2_32(MAX(CEILING_LOG2(cq_entries * 8), + LOG_CACHE_LINE_SIZE)) - 1; SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PBAX_QUEUE); SSX_ERROR_IF((((uint32_t)(cq_base) & align_mask) != 0) || @@ -978,22 +1038,24 @@ pbax_queue_create(PbaxQueue *queue, queue->cq_entries = cq_entries; queue->protocol = protocol; - switch (engine) { + switch (engine) + { - case ASYNC_ENGINE_PBAX_PUSH0: - queue->irq = OCCHW_IRQ_PBAX_OCC_PUSH0; - queue->engine = PBAX_ENGINE_PUSH0; - break; + case ASYNC_ENGINE_PBAX_PUSH0: + queue->irq = OCCHW_IRQ_PBAX_OCC_PUSH0; + queue->engine = PBAX_ENGINE_PUSH0; + break; - case ASYNC_ENGINE_PBAX_PUSH1: - queue->irq = OCCHW_IRQ_PBAX_OCC_PUSH1; - queue->engine = PBAX_ENGINE_PUSH1; - break; + case ASYNC_ENGINE_PBAX_PUSH1: + queue->irq = OCCHW_IRQ_PBAX_OCC_PUSH1; + queue->engine = PBAX_ENGINE_PUSH1; + break; - default: - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_PBAX); - } + default: + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_PBAX); + } } async_queue_create(async_queue, engine); @@ -1019,7 +1081,7 @@ pbax_queue_create(PbaxQueue *queue, SSX_IRQ_FAST2FULL(pbax_async_handler, pbax_async_handler_full); void -pbax_async_handler_full(void *arg, SsxIrqId irq, int priority) +pbax_async_handler_full(void* arg, SsxIrqId irq, int priority) { AsyncQueue* async_queue = (AsyncQueue*)arg; PbaxQueue* queue = (PbaxQueue*)async_queue; @@ -1027,23 +1089,29 @@ pbax_async_handler_full(void *arg, SsxIrqId irq, int priority) size_t read; int rc; - if (SSX_ERROR_CHECK_KERNEL && (request == 0)) { + if (SSX_ERROR_CHECK_KERNEL && (request == 0)) + { SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_PBAX); } rc = pbax_read(queue, request->current, request->remaining, &read); - if (rc) { + if (rc) + { ssx_irq_disable(queue->irq); async_error_handler(async_queue, ASYNC_REQUEST_STATE_FAILED); - } else if (read == request->remaining) { + } + else if (read == request->remaining) + { ssx_irq_disable(queue->irq); async_handler(async_queue); - } else { + } + else + { request->current += (read / 8); request->remaining -= read; @@ -1090,7 +1158,7 @@ pbax_async_handler_full(void *arg, SsxIrqId irq, int priority) SSX_IRQ_FAST2FULL(pba_error_handler, pba_error_handler_full); void -pba_error_handler_full(void *arg, SsxIrqId irq, int priority) +pba_error_handler_full(void* arg, SsxIrqId irq, int priority) { pba_fir_t fir; pba_bcde_stat_t bcde_stat; @@ -1109,27 +1177,38 @@ pba_error_handler_full(void *arg, SsxIrqId irq, int priority) xrcvstat.words.high_order = in32(PBA_XRCVSTAT); queue = (AsyncQueue*)(&G_pba_bcde_queue); + if (bcde_stat.fields.error && - (queue->state == ASYNC_QUEUE_STATE_RUNNING)) { + (queue->state == ASYNC_QUEUE_STATE_RUNNING)) + { async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); } queue = (AsyncQueue*)(&G_pba_bcue_queue); - if (bcue_stat.fields.error && - (queue->state == ASYNC_QUEUE_STATE_RUNNING)) { + + if (bcue_stat.fields.error && + (queue->state == ASYNC_QUEUE_STATE_RUNNING)) + { async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); } - if (xsndstat.fields.snd_error) { + if (xsndstat.fields.snd_error) + { pbax_send_ffdc(&G_pba_ffdc.pbax_send); } - if (xrcvstat.fields.rcv_error) { - for (channel = 0; channel < PBAX_CHANNELS; channel++) { + if (xrcvstat.fields.rcv_error) + { + for (channel = 0; channel < PBAX_CHANNELS; channel++) + { queue = (AsyncQueue*)(&G_pbax_read_queue[channel]); - if (queue->state == ASYNC_REQUEST_STATE_RUNNING) { + + if (queue->state == ASYNC_REQUEST_STATE_RUNNING) + { async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); - } else { + } + else + { pbax_receive_ffdc(&G_pba_ffdc.pbax_receive); } } @@ -1138,52 +1217,53 @@ pba_error_handler_full(void *arg, SsxIrqId irq, int priority) // Any FIR bits not already attributable to previously handled errors are // assumed to be due to the generic bridge. - if (fir.value & + if (fir.value & ( - PBA_FIR_OCI_APAR_ERR || - PBA_FIR_PB_RDADRERR_FW || - PBA_FIR_PB_RDDATATO_FW || - PBA_FIR_PB_SUE_FW || - PBA_FIR_PB_UE_FW || - PBA_FIR_PB_CE_FW || - PBA_FIR_OCI_SLAVE_INIT || - PBA_FIR_OCI_WRPAR_ERR || - PBA_FIR_OCI_REREQTO || - PBA_FIR_PB_UNEXPCRESP || - PBA_FIR_PB_UNEXPDATA || - PBA_FIR_PB_PARITY_ERR || - PBA_FIR_PB_WRADRERR_FW || - PBA_FIR_PB_BADCRESP || - PBA_FIR_PB_ACKDEAD_FW || - PBA_FIR_PB_CRESPTO || - // PBA_FIR_BCUE_SETUP_ERR || - // PBA_FIR_BCUE_PB_ACK_DEAD || - // PBA_FIR_BCUE_PB_ADRERR || - // PBA_FIR_BCUE_OCI_DATAERR || - // PBA_FIR_BCDE_SETUP_ERR || - // PBA_FIR_BCDE_PB_ACK_DEAD || - // PBA_FIR_BCDE_PB_ADRERR || - // PBA_FIR_BCDE_RDDATATO_ERR || - // PBA_FIR_BCDE_SUE_ERR || - // PBA_FIR_BCDE_UE_ERR || - // PBA_FIR_BCDE_CE || - // PBA_FIR_BCDE_OCI_DATAERR || - PBA_FIR_INTERNAL_ERR || - PBA_FIR_ILLEGAL_CACHE_OP || - PBA_FIR_OCI_BAD_REG_ADDR || - // PBA_FIR_AXPUSH_WRERR || - // PBA_FIR_AXRCV_DLO_ERR || - // PBA_FIR_AXRCV_DLO_TO || - // PBA_FIR_AXRCV_RSVDATA_TO || - // PBA_FIR_AXFLOW_ERR || - // PBA_FIR_AXSND_DHI_RTYTO || - // PBA_FIR_AXSND_DLO_RTYTO || - // PBA_FIR_AXSND_RSVTO || - // PBA_FIR_AXSND_RSVERR || - PBA_FIR_FIR_PARITY_ERR || - PBA_FIR_FIR_PARITY_ERR2 - ) - ) { + PBA_FIR_OCI_APAR_ERR || + PBA_FIR_PB_RDADRERR_FW || + PBA_FIR_PB_RDDATATO_FW || + PBA_FIR_PB_SUE_FW || + PBA_FIR_PB_UE_FW || + PBA_FIR_PB_CE_FW || + PBA_FIR_OCI_SLAVE_INIT || + PBA_FIR_OCI_WRPAR_ERR || + PBA_FIR_OCI_REREQTO || + PBA_FIR_PB_UNEXPCRESP || + PBA_FIR_PB_UNEXPDATA || + PBA_FIR_PB_PARITY_ERR || + PBA_FIR_PB_WRADRERR_FW || + PBA_FIR_PB_BADCRESP || + PBA_FIR_PB_ACKDEAD_FW || + PBA_FIR_PB_CRESPTO || + // PBA_FIR_BCUE_SETUP_ERR || + // PBA_FIR_BCUE_PB_ACK_DEAD || + // PBA_FIR_BCUE_PB_ADRERR || + // PBA_FIR_BCUE_OCI_DATAERR || + // PBA_FIR_BCDE_SETUP_ERR || + // PBA_FIR_BCDE_PB_ACK_DEAD || + // PBA_FIR_BCDE_PB_ADRERR || + // PBA_FIR_BCDE_RDDATATO_ERR || + // PBA_FIR_BCDE_SUE_ERR || + // PBA_FIR_BCDE_UE_ERR || + // PBA_FIR_BCDE_CE || + // PBA_FIR_BCDE_OCI_DATAERR || + PBA_FIR_INTERNAL_ERR || + PBA_FIR_ILLEGAL_CACHE_OP || + PBA_FIR_OCI_BAD_REG_ADDR || + // PBA_FIR_AXPUSH_WRERR || + // PBA_FIR_AXRCV_DLO_ERR || + // PBA_FIR_AXRCV_DLO_TO || + // PBA_FIR_AXRCV_RSVDATA_TO || + // PBA_FIR_AXFLOW_ERR || + // PBA_FIR_AXSND_DHI_RTYTO || + // PBA_FIR_AXSND_DLO_RTYTO || + // PBA_FIR_AXSND_RSVTO || + // PBA_FIR_AXSND_RSVERR || + PBA_FIR_FIR_PARITY_ERR || + PBA_FIR_FIR_PARITY_ERR2 + ) + ) + { pba_bridge_ffdc(&(G_pba_ffdc.bridge)); } @@ -1195,11 +1275,11 @@ pba_error_handler_full(void *arg, SsxIrqId irq, int priority) //////////////////////////////////////////////////////////////////////////// void -async_bce_initialize(BceQueue *queue, int engine, SsxIrqId irq) +async_bce_initialize(BceQueue* queue, int engine, SsxIrqId irq) { bce_queue_create(queue, engine); async_level_handler_setup(bce_async_handler, - (void *)queue, + (void*)queue, irq, SSX_CRITICAL, SSX_IRQ_POLARITY_ACTIVE_HIGH); @@ -1208,13 +1288,13 @@ async_bce_initialize(BceQueue *queue, int engine, SsxIrqId irq) void -async_pbax_initialize(PbaxQueue *queue, int engine, SsxIrqId irq, - uint64_t *buffer, size_t length, int protocol) +async_pbax_initialize(PbaxQueue* queue, int engine, SsxIrqId irq, + uint64_t* buffer, size_t length, int protocol) { pbax_queue_create(queue, engine, buffer, length, protocol); pbax_queue_enable(queue); async_level_handler_setup(pbax_async_handler, - (void *)queue, + (void*)queue, irq, SSX_NONCRITICAL, SSX_IRQ_POLARITY_ACTIVE_HIGH); diff --git a/src/ssx/occhw/occhw_cache.S b/src/ssx/occhw/occhw_cache.S index 052021b..1a7a05b 100644 --- a/src/ssx/occhw/occhw_cache.S +++ b/src/ssx/occhw/occhw_cache.S @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/occhw/occhw_core.h b/src/ssx/occhw/occhw_core.h index b576e40..c483f6f 100644 --- a/src/ssx/occhw/occhw_core.h +++ b/src/ssx/occhw/occhw_core.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/occhw/occhw_id.c b/src/ssx/occhw/occhw_id.c index ab6f5bc..816ae0c 100644 --- a/src/ssx/occhw/occhw_id.c +++ b/src/ssx/occhw/occhw_id.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -80,7 +80,7 @@ cfam_id(void) return G_cfam_id; } -uint8_t +uint8_t cfam_chip_type(void) { return G_cfam_chip_type; @@ -101,7 +101,7 @@ cfam_ec_level(void) // Note: Ex-chiplets start at chiplet 16 and are left-justified in the // ChipConfig. - + ChipConfig G_chip_configuration SECTION_ATTRIBUTE(".noncacheable") = 0; uint64_t G_core_configuration SECTION_ATTRIBUTE(".noncacheable") = 0; @@ -115,29 +115,44 @@ uint64_t G_core_configuration SECTION_ATTRIBUTE(".noncacheable") = 0; void _occhw_get_chip_configuration(void) { - if (SIMICS_ENVIRONMENT) { + if (SIMICS_ENVIRONMENT) + { pmc_core_deconfiguration_reg_t pcdr; pcdr.value = in32(PMC_CORE_DECONFIGURATION_REG); - G_chip_configuration = - ~((uint64_t)(pcdr.fields.core_chiplet_deconf_vector) << 48); + G_chip_configuration = + ~((uint64_t)(pcdr.fields.core_chiplet_deconf_vector) << 48); - } else { + } + else + { uint64_t select, configuration; int rc; - + rc = getscom(0x000f0008, &select); /* TP CHIPLET SELECT */ - if (rc) SSX_PANIC(OCCHW_ID_SCOM_ERROR_SELECT); - if (select != 0) SSX_PANIC(OCCHW_ID_SELECT_ERROR); - - rc = getscom(MC_ADDRESS(0x000f0012, - MC_GROUP_EX_CORE, - PCB_MULTICAST_SELECT), + + if (rc) + { + SSX_PANIC(OCCHW_ID_SCOM_ERROR_SELECT); + } + + if (select != 0) + { + SSX_PANIC(OCCHW_ID_SELECT_ERROR); + } + + rc = getscom(MC_ADDRESS(0x000f0012, + MC_GROUP_EX_CORE, + PCB_MULTICAST_SELECT), &configuration); - if (rc) SSX_PANIC(OCCHW_ID_SCOM_ERROR_CONFIG); - + + if (rc) + { + SSX_PANIC(OCCHW_ID_SCOM_ERROR_CONFIG); + } + G_chip_configuration = (configuration << 16) & 0xffff000000000000ull; } @@ -150,8 +165,8 @@ uint32_t core_configuration(void) return G_core_configuration >> 32; } - - - + + + diff --git a/src/ssx/occhw/occhw_id.h b/src/ssx/occhw/occhw_id.h index d591f6a..d9c2b56 100644 --- a/src/ssx/occhw/occhw_id.h +++ b/src/ssx/occhw/occhw_id.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -54,7 +54,7 @@ /// For example, to identify a chip as Murano DD1.0, one could use either /// method shown below: /// -/// \code +/// \code /// /// if (cfam_id() == CFAM_CHIP_ID_MURANO_10) { ... } /// @@ -72,50 +72,50 @@ #ifndef __ASSEMBLER__ -#include <stdint.h> -#include "tpc_firmware_registers.h" + #include <stdint.h> + #include "tpc_firmware_registers.h" -/// Get TPC device identification (internal API, called once from __occhw_setup(). -void -_occhw_get_ids(void); + /// Get TPC device identification (internal API, called once from __occhw_setup(). + void + _occhw_get_ids(void); -/// Get the TPC Node Id -uint8_t node_id(void); + /// Get the TPC Node Id + uint8_t node_id(void); -/// Get the TPC Chip Id -uint8_t chip_id(void); + /// Get the TPC Chip Id + uint8_t chip_id(void); -/// Get the CFAM Chip Id -/// -/// \returns A 32-bit value to be compared against the enumeration of known -/// CFAM ids. See \ref cfam_chip_ids. -uint32_t cfam_id(void); + /// Get the CFAM Chip Id + /// + /// \returns A 32-bit value to be compared against the enumeration of known + /// CFAM ids. See \ref cfam_chip_ids. + uint32_t cfam_id(void); -/// Get the CFAM Chip Type -/// -/// \returns An 8-bit value to be compared against the enumeration of known -/// CFAM chip types. See \ref cfam_chip_types. -uint8_t cfam_chip_type(void); + /// Get the CFAM Chip Type + /// + /// \returns An 8-bit value to be compared against the enumeration of known + /// CFAM chip types. See \ref cfam_chip_types. + uint8_t cfam_chip_type(void); -/// Get the CFAM Chip EC Level -/// -/// \returns An 8-bit value; The high-order nibble is the major EC level and -/// the low-order nibble is the minor EC level. Fore example a value of 0x21 -/// indicates DD 2.1. -uint8_t cfam_ec_level(void); + /// Get the CFAM Chip EC Level + /// + /// \returns An 8-bit value; The high-order nibble is the major EC level and + /// the low-order nibble is the minor EC level. Fore example a value of 0x21 + /// indicates DD 2.1. + uint8_t cfam_ec_level(void); -/// Compute the chip configuration (internal API, called once from __occhw_setup(). -void -_occhw_get_chip_configuration(void); + /// Compute the chip configuration (internal API, called once from __occhw_setup(). + void + _occhw_get_chip_configuration(void); -/// Get the core configuration -/// -/// The return value is a 32 bit integer with big-endian bits set to indicate -/// valid cores. -uint32_t -core_configuration(void); + /// Get the core configuration + /// + /// The return value is a 32 bit integer with big-endian bits set to indicate + /// valid cores. + uint32_t + core_configuration(void); #endif // __ASSEMBLER__ @@ -138,9 +138,9 @@ core_configuration(void); /// \defgroup cfam_chip_ids CFAM Chip Ids (Including Centaur) /// /// The CFAM Chip ID is a 32-bit value that uniquely identfies a chip and its -/// EC level. +/// EC level. /// -/// The reference: +/// The reference: /// /// - https://eclipz.pok.ibm.com/sys/ras/docs/cfam_ids.txt /// @@ -175,9 +175,11 @@ core_configuration(void); /// The CFAM ID as a set of fields -typedef union { +typedef union +{ #ifdef _BIG_ENDIAN - struct { + struct + { uint32_t majorEc : 4; uint32_t location : 4; uint32_t minorEc : 4; @@ -185,7 +187,8 @@ typedef union { uint32_t vendor : 12; }; #else - struct { + struct + { uint32_t vendor : 12; uint32_t chipType : 8; uint32_t minorEc : 4; diff --git a/src/ssx/occhw/occhw_init.c b/src/ssx/occhw/occhw_init.c index bbb67bd..0ac9805 100644 --- a/src/ssx/occhw/occhw_init.c +++ b/src/ssx/occhw/occhw_init.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -43,8 +43,8 @@ #include "string_stream.h" #if USE_RTX_IO -// This file is not avilable to OCC FW builds -#include "rtx_stdio.h" + // This file is not avilable to OCC FW builds + #include "rtx_stdio.h" #endif // We need to make sure that the PLB arbiter is set up correctly to obtain @@ -101,29 +101,30 @@ plb_arbiter_setup() // defined on cacheable data sections. #ifdef CACHE_INHIBIT_ALL -#define CACHE_INHIBIT_TEXT 1 -#define CACHE_INHIBIT_DATA 1 + #define CACHE_INHIBIT_TEXT 1 + #define CACHE_INHIBIT_DATA 1 #endif #if CACHE_INHIBIT_TEXT -#define TEXT_CACHEABILITY_FLAG TLBLO_I + #define TEXT_CACHEABILITY_FLAG TLBLO_I #else -#define TEXT_CACHEABILITY_FLAG 0 + #define TEXT_CACHEABILITY_FLAG 0 #endif #if CACHE_INHIBIT_DATA -#define DATA_CACHEABILITY_FLAG TLBLO_I -#define WRITETHROUGH_FLAG 0 + #define DATA_CACHEABILITY_FLAG TLBLO_I + #define WRITETHROUGH_FLAG 0 #else -#define DATA_CACHEABILITY_FLAG 0 -#define WRITETHROUGH_FLAG TLBLO_W + #define DATA_CACHEABILITY_FLAG 0 + #define WRITETHROUGH_FLAG TLBLO_W #endif // This structure contains all of the fields necessary to create a MMU // mapping. -typedef struct { +typedef struct +{ SsxAddress base; size_t size; uint32_t tlbhi_flags; @@ -136,58 +137,64 @@ typedef struct { // mappings may be later modified. Ppc405MmuMap G_ex_free_mmu_map; -Ppc405MmuMap G_applet0_mmu_map; -Ppc405MmuMap G_applet1_mmu_map; - -static const MmuRegion mmu_regions[] = { - - {(SsxAddress)&_TEXT0_SECTION_BASE, - (size_t)&_TEXT0_SECTION_SIZE, - 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0} , - - {(SsxAddress)&_TEXT1_SECTION_BASE, - (size_t)&_TEXT1_SECTION_SIZE, - 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0} , - - {(SsxAddress)&_RODATA_SECTION_BASE, - (size_t)&_RODATA_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG, 0} , - - {(SsxAddress)&_NONCACHEABLE_RO_SECTION_BASE, - (size_t)&_NONCACHEABLE_RO_SECTION_SIZE, - 0, TLBLO_I, 0} , - - {(SsxAddress)&_NONCACHEABLE_SECTION_BASE, - (size_t)&_NONCACHEABLE_SECTION_SIZE, - 0, TLBLO_I | TLBLO_WR, 0} , - - {(SsxAddress)&_WRITETHROUGH_SECTION_BASE, - (size_t)&_WRITETHROUGH_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG | WRITETHROUGH_FLAG | TLBLO_WR, 0} , - - {(SsxAddress)&_DATA_SECTION_BASE, - (size_t)&_DATA_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG | TLBLO_WR, 0} , - - {(SsxAddress)&_EX_FREE_SECTION_BASE, - (size_t)&_EX_FREE_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_EX | TLBLO_WR, - &G_ex_free_mmu_map}, - -/* - {(SsxAddress)&_APPLET0_SECTION_BASE, - (size_t)&_APPLET0_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_WR | TLBLO_EX, - &G_applet0_mmu_map}, - - {(SsxAddress)&_APPLET1_SECTION_BASE, - (size_t)&_APPLET1_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_WR | TLBLO_EX, - &G_applet1_mmu_map}, -*/ - {(SsxAddress)OCI_REGISTER_SPACE_BASE, - (size_t)OCI_REGISTER_SPACE_SIZE, - 0, TLBLO_WR | TLBLO_I | TLBLO_G, 0} , + +static const MmuRegion mmu_regions[] = +{ + + { + (SsxAddress)& _TEXT0_SECTION_BASE, + (size_t)& _TEXT0_SECTION_SIZE, + 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0 + } , + + { + (SsxAddress)& _TEXT1_SECTION_BASE, + (size_t)& _TEXT1_SECTION_SIZE, + 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0 + } , + + { + (SsxAddress)& _RODATA_SECTION_BASE, + (size_t)& _RODATA_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG, 0 + } , + + { + (SsxAddress)& _NONCACHEABLE_RO_SECTION_BASE, + (size_t)& _NONCACHEABLE_RO_SECTION_SIZE, + 0, TLBLO_I, 0 + } , + + { + (SsxAddress)& _NONCACHEABLE_SECTION_BASE, + (size_t)& _NONCACHEABLE_SECTION_SIZE, + 0, TLBLO_I | TLBLO_WR, 0 + } , + + { + (SsxAddress)& _WRITETHROUGH_SECTION_BASE, + (size_t)& _WRITETHROUGH_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG | WRITETHROUGH_FLAG | TLBLO_WR, 0 + } , + + { + (SsxAddress)& _DATA_SECTION_BASE, + (size_t)& _DATA_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG | TLBLO_WR, 0 + } , + + { + (SsxAddress)& _EX_FREE_SECTION_BASE, + (size_t)& _EX_FREE_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_EX | TLBLO_WR, + &G_ex_free_mmu_map + }, + + { + (SsxAddress)OCI_REGISTER_SPACE_BASE, + (size_t)OCI_REGISTER_SPACE_SIZE, + 0, TLBLO_WR | TLBLO_I | TLBLO_G, 0 + } , }; /// OCCHW MMU setup @@ -208,8 +215,11 @@ occhw_mmu_setup() ppc405_mmu_reset(); regions = sizeof(mmu_regions) / sizeof(MmuRegion); - for (i = 0; i < regions; i++) { - if (mmu_regions[i].size != 0) { + + for (i = 0; i < regions; i++) + { + if (mmu_regions[i].size != 0) + { ppc405_mmu_map(mmu_regions[i].base, mmu_regions[i].base, mmu_regions[i].size, @@ -261,19 +271,19 @@ io_setup() SSXOUT_TRACE_BUFFER_SIZE, SSX_FILE_OP_LOCK_CRITICAL); - stdout = (FILE *)(&G_ssxout); - stderr = (FILE *)(&G_ssxout); - ssxout = (FILE *)(&G_ssxout); + stdout = (FILE*)(&G_ssxout); + stderr = (FILE*)(&G_ssxout); + ssxout = (FILE*)(&G_ssxout); #elif USE_EPM_IO linear_stream_create(&G_ssxout, &G_ssxout_buffer, - SSXOUT_TRACE_BUFFER_SIZE, - SSX_FILE_OP_LOCK_CRITICAL); + SSXOUT_TRACE_BUFFER_SIZE, + SSX_FILE_OP_LOCK_CRITICAL); - stdout = (FILE *)(&G_ssxout); - stderr = (FILE *)(&G_ssxout); - ssxout = (FILE *)(&G_ssxout); + stdout = (FILE*)(&G_ssxout); + stderr = (FILE*)(&G_ssxout); + ssxout = (FILE*)(&G_ssxout); #elif USE_RTX_IO @@ -281,10 +291,10 @@ io_setup() rtx_stdout_create(&rtx_stdout); rtx_stderr_create(&rtx_stderr); - stdin = (FILE *)(&rtx_stdin); - stdout = (FILE *)(&rtx_stdout); - stderr = (FILE *)(&rtx_stderr); - ssxout = (FILE *)(&rtx_stdout); + stdin = (FILE*)(&rtx_stdin); + stdout = (FILE*)(&rtx_stdout); + stderr = (FILE*)(&rtx_stderr); + ssxout = (FILE*)(&rtx_stdout); printf("Initialize the RTX stdio.\n"); printf("RTX stdin is not implemented.\n"); @@ -295,10 +305,10 @@ io_setup() simics_stdout_create(&simics_stdout); simics_stderr_create(&simics_stderr); - stdin = (FILE *)(&simics_stdin); - stdout = (FILE *)(&simics_stdout); - stderr = (FILE *)(&simics_stderr); - ssxout = (FILE *)(&simics_stdout); + stdin = (FILE*)(&simics_stdin); + stdout = (FILE*)(&simics_stdout); + stderr = (FILE*)(&simics_stderr); + ssxout = (FILE*)(&simics_stdout); printf("Initialize the Simics stdio.\n"); @@ -390,7 +400,7 @@ __occhw_setup() // Setup requires SCOM, which requires a timeout. Therefore we need to set // up a default timebase frequency, which may be overridden during - // ssx_initialize(). + // ssx_initialize(). __ssx_timebase_frequency_hz = 600000000; __ssx_timebase_frequency_khz = 600000; diff --git a/src/ssx/occhw/occhw_irq.h b/src/ssx/occhw/occhw_irq.h index b5c25c0..aea8b41 100644 --- a/src/ssx/occhw/occhw_irq.h +++ b/src/ssx/occhw/occhw_irq.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -52,7 +52,7 @@ #ifndef __ASSEMBLER__ -/// Enable an interrupt by clearing the mask bit. +/// Enable an interrupt by clearing the mask bit. UNLESS__PPC405_IRQ_CORE_C__(extern) inline void @@ -99,9 +99,12 @@ UNLESS__PPC405_IRQ_CORE_C__(extern) inline void ssx_irq_status_set(SsxIrqId irq, int value) { - if (value) { + if (value) + { out32(OCCHW_OISR_OR(irq), OCCHW_IRQ_MASK32(irq)); - } else { + } + else + { out32(OCCHW_OISR_CLR(irq), OCCHW_IRQ_MASK32(irq)); } } @@ -121,18 +124,18 @@ ssx_irq_debug_set(SsxIrqId irq, int value); /// /// \arg \c rirq A register that holds the \c irq parameter passed to /// the handler from SSX interrupt dispatch. This register is not -/// modified. +/// modified. /// \arg \c rmask A scratch register - At the end of macro execution this /// register contains the 32-bit mask form of the irq. /// /// \arg \c raddr A scratch register - At the end of macro execution this -/// register holds the address of the interrupt +/// register holds the address of the interrupt /// controller facility that implements the action. /// /// \arg \c imm An immediate (0/non-0) value for certain macros. /// /// Forms: -/// +/// /// \b _ssx_irq_enable \a rirq, \a rmask, \a raddr - Enable an \c irq. \n /// \b _ssx_irq_disable \a rirq, \a rmask, \a raddr - Disable an \c irq. \n /// \b _ssx_irq_status_clear \a rirq, \a rmask, \a raddr - Clear \c irq @@ -153,10 +156,11 @@ ssx_irq_debug_set(SsxIrqId irq, int value); // register \c raddr is used as scratch for these computations. Hopefully the // local labels 888 and 999 are unique enough. -// Register names must be compared as strings - e.g., %r0 is not +// Register names must be compared as strings - e.g., %r0 is not // a symbol, it is converted to "0" by the assembler. #ifdef __ASSEMBLER__ +// *INDENT-OFF* .macro .two_unique, ra, rb .ifnc \ra, \rb @@ -192,7 +196,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); .macro _ssx_irq_enable, rirq:req, rmask:req, raddr:req .three_unique \rirq, \rmask, \raddr - + andi. \raddr, \rirq, 0x20 clrlwi \raddr, \rirq, 27 _occhw_irq_clr_mask \raddr, \rmask @@ -208,7 +212,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); .macro _ssx_irq_disable, rirq:req, rmask:req, raddr:req .three_unique \rirq, \rmask, \raddr - + andi. \raddr, \rirq, 0x20 clrlwi \raddr, \rirq, 27 _occhw_irq_or_mask \raddr, \rmask @@ -224,7 +228,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); .macro _ssx_irq_status_clear, rirq:req, rmask:req, raddr:req .three_unique \rirq, \rmask, \raddr - + andi. \raddr, \rirq, 0x20 clrlwi \raddr, \rirq, 27 _occhw_irq_clr_mask \raddr, \rmask @@ -243,7 +247,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); andi. \raddr, \rirq, 0x20 clrlwi \raddr, \rirq, 27 - + .if \imm _occhw_irq_or_mask \raddr, \rmask bne- 888f @@ -253,7 +257,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); _stwi \rmask, \raddr, OCB_OISR1_OR .else - + _occhw_irq_clr_mask \raddr, \rmask bne- 888f _stwi \rmask, \raddr, OCB_OISR0_CLR @@ -266,6 +270,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); eieio .endm +// *INDENT-ON* #endif /* __ASSEMBLER__ */ /// \endcond diff --git a/src/ssx/occhw/occhw_irq_init.c b/src/ssx/occhw/occhw_irq_init.c index da10cda..86e4562 100644 --- a/src/ssx/occhw/occhw_irq_init.c +++ b/src/ssx/occhw/occhw_irq_init.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -52,7 +52,7 @@ /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_ARGUMENT_IRQ_SETUP One or more arguments are invalid, +/// \retval -SSX_INVALID_ARGUMENT_IRQ_SETUP One or more arguments are invalid, /// including an invalid \a irq, or invalid \a polarity or \a trigger parameters. int @@ -62,7 +62,8 @@ ssx_irq_setup(SsxIrqId irq, { SsxMachineContext ctx; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(!OCCHW_IRQ_VALID(irq) || !OCCHW_IRQ_OWNED(irq) || !((polarity == SSX_IRQ_POLARITY_ACTIVE_HIGH) || @@ -74,15 +75,21 @@ ssx_irq_setup(SsxIrqId irq, ssx_critical_section_enter(SSX_CRITICAL, &ctx); - if (polarity == SSX_IRQ_POLARITY_ACTIVE_HIGH) { + if (polarity == SSX_IRQ_POLARITY_ACTIVE_HIGH) + { out32(OCCHW_OIEPR_OR(irq), OCCHW_IRQ_MASK32(irq)); - } else { + } + else + { out32(OCCHW_OIEPR_CLR(irq), OCCHW_IRQ_MASK32(irq)); } - if (trigger == SSX_IRQ_TRIGGER_EDGE_SENSITIVE) { + if (trigger == SSX_IRQ_TRIGGER_EDGE_SENSITIVE) + { out32(OCCHW_OITR_OR(irq), OCCHW_IRQ_MASK32(irq)); - } else { + } + else + { out32(OCCHW_OITR_CLR(irq), OCCHW_IRQ_MASK32(irq)); } @@ -101,19 +108,20 @@ ssx_irq_setup(SsxIrqId irq, /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_ARGUMENT_IRQ_HANDLER One or more arguments are -/// invalid, including an invalid \a irq, a null (0) \a handler, +/// \retval -SSX_INVALID_ARGUMENT_IRQ_HANDLER One or more arguments are +/// invalid, including an invalid \a irq, a null (0) \a handler, /// or invalid \a priority. int ssx_irq_handler_set(SsxIrqId irq, SsxIrqHandler handler, - void *arg, + void* arg, int priority) { SsxMachineContext ctx; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(!OCCHW_IRQ_VALID(irq) || !OCCHW_IRQ_OWNED(irq) || (handler == 0) || @@ -129,9 +137,12 @@ ssx_irq_handler_set(SsxIrqId irq, out32(OCCHW_OIRRB_CLR(irq), OCCHW_IRQ_MASK32(irq)); //Critical priority needs a 1 in OIRRC - if (priority == SSX_CRITICAL) { + if (priority == SSX_CRITICAL) + { out32(OCCHW_OIRRC_OR(irq), OCCHW_IRQ_MASK32(irq)); - } else { + } + else + { out32(OCCHW_OIRRC_CLR(irq), OCCHW_IRQ_MASK32(irq)); } @@ -156,9 +167,12 @@ ssx_irq_debug_set(SsxIrqId irq, int value) //TODO: port this over to using the OIRR instead of the OUDER //ouder = in32(OCCHW_OUDER(irq)); - if (value) { + if (value) + { //out32(OCCHW_OUDER(irq), ouder | OCCHW_IRQ_MASK32(irq)); - } else { + } + else + { //out32(OCCHW_OUDER(irq), ouder & ~OCCHW_IRQ_MASK32(irq)); } @@ -166,15 +180,15 @@ ssx_irq_debug_set(SsxIrqId irq, int value) } - - - - - - - + + + + + + + diff --git a/src/ssx/occhw/occhw_ocb.c b/src/ssx/occhw/occhw_ocb.c index 6188abb..dcc44a2 100644 --- a/src/ssx/occhw/occhw_ocb.c +++ b/src/ssx/occhw/occhw_ocb.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -41,7 +41,7 @@ unsigned int g_ocb_timer_divider = OCB_TIMER_DIVIDER_DEFAULT; /// \param timer A valid OCB timer index /// /// \param auto_reload A non-0 value indicates to run the timer in auto-reload -/// mode. +/// mode. /// /// \param timeout_ns The timeout specified in nanoseconds. The actual timeout /// will be rounded down to the underlying timer tick, with a minimum 1 tick @@ -55,7 +55,7 @@ unsigned int g_ocb_timer_divider = OCB_TIMER_DIVIDER_DEFAULT; /// /// \retval 0 Success /// -/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer +/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer /// numbers and illegal or unrepresntable timeouts. // Note that OCB_TIMER_FREQUENCY_HZ is in the range of 1-2 MHz. @@ -68,16 +68,20 @@ ocb_timer_reset(int timer, ocb_otrn_t otr; int ticks; - //printk("ocb_timer_reset(%d, %d, %d)\n", + //printk("ocb_timer_reset(%d, %d, %d)\n", // timer, auto_reload, timeout_ns); - if (timeout_ns != 0) { + if (timeout_ns != 0) + { ticks = MAX(1, timeout_ns / (1000000000 / OCB_TIMER_FREQUENCY_HZ)); - } else { + } + else + { ticks = 0; } - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((timer < 0) || (timer >= OCB_TIMERS) || (timeout_ns < 0) || @@ -103,7 +107,7 @@ ocb_timer_reset(int timer, /// \param timer A valid OCB timer index /// /// \param auto_reload A non-0 value indicates to run the timer in auto-reload -/// mode. +/// mode. /// /// \param timeout_ns The timeout specified in nanoseconds. The actual timeout /// will rounded down to the underlying timer tick, with a minimum 1 tick @@ -116,32 +120,32 @@ ocb_timer_reset(int timer, /// \param arg The private argument of the interrupt handler /// /// \param priority The SSX/PPC405 interrupt priority to assign to the -/// interrupt. +/// interrupt. /// /// This API sets up and starts the timer and unmasks the timer /// interrupt. Once set up, the timer can be reset using ocb_timer_reset(). As /// a fine point of the specification, if a timer interrupt is already pending /// when this API is invoked then that interrupt will be cleared. Only the /// next interrupt (corresponding to the new programming) will be serviced by -/// the newly installed handler. +/// the newly installed handler. /// /// Note that the interrupt handler is responsible for clearing the timer /// interrupt status. An API ocb_timer_status_clear() is available for this. /// /// \retval 0 Success /// -/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer +/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer /// numbers and illegal or unrepresntable timeouts. /// /// Other errors may be returned by the underlying calls to SSX routines that /// set up interrupts. int -ocb_timer_setup(int timer, +ocb_timer_setup(int timer, int auto_reload, int timeout_ns, SsxIrqHandler handler, - void *arg, + void* arg, int priority) { int rc; @@ -150,35 +154,38 @@ ocb_timer_setup(int timer, do { //Read Hang Pulse Register 2 to get the log base 2 of the ocb clock divider -- grm -// TEMP : Need Simics to model this +// TEMP/TODO: Cannot do getscom from 405 +// TODO: Need to discuss this getscom and whether it is necessary. // rc = getscom(TPC_HPR2, &l_hpr2.value); + if(rc) { break; } -//David Du: l_hpr2.fields.hang_pulse_reg is typically 9 +//TEMP/TODO: l_hpr2.fields.hang_pulse_reg is typically 9 // g_ocb_timer_divider = 1 << l_hpr2.fields.hang_pulse_reg; g_ocb_timer_divider = 1 << 9; //printk("ocb_timer_setup(%d, %d, %d, %p, %p, %d)\n", // timer, auto_reload, timeout_ns, // handler, arg, priority); - + ssx_irq_disable(OCCHW_IRQ_OCC_TIMER0 + timer); ssx_irq_setup(OCCHW_IRQ_OCC_TIMER0 + timer, - SSX_IRQ_POLARITY_ACTIVE_HIGH, - SSX_IRQ_TRIGGER_LEVEL_SENSITIVE); + SSX_IRQ_POLARITY_ACTIVE_HIGH, + SSX_IRQ_TRIGGER_LEVEL_SENSITIVE); ssx_irq_handler_set(OCCHW_IRQ_OCC_TIMER0 + timer, - handler, - arg, - priority); + handler, + arg, + priority); rc = ocb_timer_reset(timer, auto_reload, timeout_ns); ssx_irq_enable(OCCHW_IRQ_OCC_TIMER0 + timer); - }while(0); + } + while(0); return rc; } @@ -220,7 +227,7 @@ ocb_core_interrupt() /// overwritten with b'11000' /// /// -/// \todo double check SRAM region restriction +/// \todo double check SRAM region restriction /// /// \param channel The indirect channel to use, in the range 0..2. /// @@ -233,7 +240,7 @@ ocb_core_interrupt() /// /// \retval 0 Success /// -/// \retval OCB_INVALID_ARGUMENT_LW_INIT One or more of the parameter +/// \retval OCB_INVALID_ARGUMENT_LW_INIT One or more of the parameter /// restrictions were violated. /// /// \retval OCB_SCOM_ERROR An attempt to write a PBA SCOM register to set up @@ -249,10 +256,11 @@ ocb_linear_window_initialize(int channel, uint32_t base, int log_size) // create mask for checking mask = (0x1ull << log_size) - 1; - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((channel < 0) || + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((channel < 0) || (channel > 3) || - (log_size < OCB_LW_LOG_SIZE_MIN) || + (log_size < OCB_LW_LOG_SIZE_MIN) || (log_size > OCB_LW_LOG_SIZE_MAX) || ((base & mask) != 0), OCB_INVALID_ARGUMENT_LW_INIT); @@ -287,7 +295,7 @@ ocb_linear_window_initialize(int channel, uint32_t base, int log_size) /// /// \retval 0 Success /// -/// \retval OCB_INVALID_ARGUMENT_LW_DISABLE One or more of the parameter +/// \retval OCB_INVALID_ARGUMENT_LW_DISABLE One or more of the parameter /// restrictions were violated. /// @@ -295,15 +303,16 @@ int ocb_linear_window_disable(int channel) { ocb_ocblwcrn_t ocblwcrn; - - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((channel < 0) || + + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((channel < 0) || (channel > 3), OCB_INVALID_ARGUMENT_LW_DISABLE); } ocblwcrn.value = in32(OCB_OCBLWCRN(channel)); - // Disable LW mode + // Disable LW mode ocblwcrn.fields.linear_window_enable = 0; out32(OCB_OCBLWCRN(channel), ocblwcrn.value); @@ -323,7 +332,7 @@ ocb_linear_window_disable(int channel) /// Note that this bit is not used for indirect channel 3. /// /// -/// \param allow_untrusted Enable untrusted PIB masters +/// \param allow_untrusted Enable untrusted PIB masters /// access to the indirect channel being configured. If allow_untrusted is /// not enabled and the chip is running in trusted mode, then any untrusted /// PIB master will get an offline return code when attempting to write @@ -331,7 +340,7 @@ ocb_linear_window_disable(int channel) /// /// \retval 0 Success /// -/// \retval OCB_INVALID_ARGUMENT_UNTRUST One or more of the parameter +/// \retval OCB_INVALID_ARGUMENT_UNTRUST One or more of the parameter /// restrictions were violated. /// @@ -344,8 +353,9 @@ ocb_allow_untrusted_initialize(int channel, int allow_untrusted) { ocb_ocbicrn_t ocbicrn; - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((channel < 0) || + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((channel < 0) || (channel > 2) || (allow_untrusted < 0) || (allow_untrusted > 1), @@ -354,7 +364,7 @@ ocb_allow_untrusted_initialize(int channel, int allow_untrusted) // Configure allow_unsecure_pib_masters bit ocbicrn.fields.allow_unsecure_pib_masters = allow_untrusted; - out32(OCB_OCBICRN(channel), ocbicrn.value); + out32(OCB_OCBICRN(channel), ocbicrn.value); return 0 ; } diff --git a/src/ssx/occhw/occhw_ocb.h b/src/ssx/occhw/occhw_ocb.h index 9a780b4..6e873ce 100644 --- a/src/ssx/occhw/occhw_ocb.h +++ b/src/ssx/occhw/occhw_ocb.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -61,27 +61,27 @@ #ifndef __ASSEMBLER__ -int -ocb_timer_reset(int timer, +int +ocb_timer_reset(int timer, int auto_reload, int timeout_ns); #ifdef OCC int -ocb_timer_setup(int timer, +ocb_timer_setup(int timer, int auto_reload, int timeout_ns, SsxIrqHandler handler, - void *arg, + void* arg, int priority) INIT_SECTION; #else int ocb_timer_setup(int timer, - int auto_reload, - int timeout_ns, - SsxIrqHandler handler, - void *arg, - int priority); + int auto_reload, + int timeout_ns, + SsxIrqHandler handler, + void* arg, + int priority); #endif /// Clear OCB timer status based on the IRQ @@ -106,7 +106,7 @@ ocb_linear_window_disable(int channel); int ocb_allow_untrusted_initialize(int channel, int allow_untrusted); - + #endif /* __ASSEMBLER__ */ diff --git a/src/ssx/occhw/occhw_pba.c b/src/ssx/occhw/occhw_pba.c index 5ba18d5..35344ba 100644 --- a/src/ssx/occhw/occhw_pba.c +++ b/src/ssx/occhw/occhw_pba.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,14 +40,14 @@ // Internal API to set up a PBA BAR -static int +static int pba_bar_set(int idx, uint64_t pb_base, uint8_t pb_scope) { int rc ; pba_barn_t bar ; bar.fields.cmd_scope = pb_scope ; - bar.fields.addr = pb_base >> PBA_LOG_SIZE_MIN ; + bar.fields.addr = pb_base >> PBA_LOG_SIZE_MIN ; rc = putscom(PBA_BARN(idx), bar.value); @@ -93,10 +93,10 @@ pba_barmask_set(int idx, uint64_t mask) /// /// \retval 0 Success /// -/// \retval PBA_INVALID_ARGUMENT_BARSET One or more of the parameter +/// \retval PBA_INVALID_ARGUMENT_BARSET One or more of the parameter /// restrictions were violated. /// -/// \retval PBA_SCOM_ERROR1 or PBA_SCOM_ERROR2 An attempt to write a PBA SCOM +/// \retval PBA_SCOM_ERROR1 or PBA_SCOM_ERROR2 An attempt to write a PBA SCOM /// register to set up the BARs produced a non-zero return code. int @@ -106,21 +106,25 @@ pba_barset_initialize(int idx, uint64_t base, int log_size) mask = (0x1ull << log_size) - 1; - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((idx < 0) || + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((idx < 0) || (idx > 3) || - (log_size < PBA_LOG_SIZE_MIN) || + (log_size < PBA_LOG_SIZE_MIN) || (log_size > PBA_LOG_SIZE_MAX) || ((base & mask) != 0), PBA_INVALID_ARGUMENT_BARSET); } - if (pba_bar_set(idx, base, PBA_POWERBUS_COMMAND_SCOPE_DEFAULT)) { + if (pba_bar_set(idx, base, PBA_POWERBUS_COMMAND_SCOPE_DEFAULT)) + { SSX_ERROR(PBA_SCOM_ERROR1); } - if (pba_barmask_set(idx, mask)) { + + if (pba_barmask_set(idx, mask)) + { SSX_ERROR(PBA_SCOM_ERROR2); - } + } return 0 ; } @@ -159,7 +163,7 @@ _pba_slave_reset_poll(void* arg, int* done) } -/// Reset a PBA slave with explicit timeout. +/// Reset a PBA slave with explicit timeout. /// /// \param id A PBA slave id in the range 0..3 /// @@ -175,7 +179,7 @@ _pba_slave_reset_poll(void* arg, int* done) /// /// \retval 0 Success /// -/// \retval -PBA_INVALID_ARGUMENT_RESET The slave \a id parameter +/// \retval -PBA_INVALID_ARGUMENT_RESET The slave \a id parameter /// is invalid. /// /// \retval -PBA_SLVRST_TIMED_OUT1 The procedure timed out waiting for the PBA @@ -187,13 +191,16 @@ _pba_slave_reset(int id, SsxInterval timeout, SsxInterval sleep) { int rc, closureRc; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((id < 0) || (id >= PBA_SLAVES), PBA_INVALID_ARGUMENT_RESET); } - + rc = polling(&closureRc, _pba_slave_reset_poll, (void*)id, timeout, sleep); - if (rc == POLLING_TIMEOUT) { + + if (rc == POLLING_TIMEOUT) + { rc = -PBA_SLVRST_TIMED_OUT1; } @@ -213,7 +220,7 @@ _pba_slave_reset(int id, SsxInterval timeout, SsxInterval sleep) /// /// \retval 0 Success /// -/// \retval -SSX_INVALID_ARGUMENT_PBA_RESET The slave \a id parameter is +/// \retval -SSX_INVALID_ARGUMENT_PBA_RESET The slave \a id parameter is /// invalid. /// /// \retval -PBA_SLVRST_TIMED_OUT2 The procedure timed out waiting for the PBA @@ -225,7 +232,9 @@ pba_slave_reset(int id) int rc; rc = _pba_slave_reset(id, PBA_SLAVE_RESET_TIMEOUT, 0); - if (rc) { + + if (rc) + { SSX_ERROR(PBA_SLVRST_TIMED_OUT2); } @@ -253,15 +262,16 @@ pba_slave_reset(int id) /// /// \retval 0 Success /// -/// \retval -PBAX_INVALID_ARGUMENT_CONFIG One of the arguments is -/// not valid for some reason. +/// \retval -PBAX_INVALID_ARGUMENT_CONFIG One of the arguments is +/// not valid for some reason. int pbax_configure(int master, int group, int chip, int group_mask) { pba_xcfg_t pxc; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((group < 0) || (group >= PBAX_GROUPS) || (chip < 0) || @@ -270,6 +280,7 @@ pbax_configure(int master, int group, int chip, int group_mask) (group_mask > PBAX_GROUP_MASK_MAX), PBAX_INVALID_ARGUMENT_CONFIG); } + pxc.value = in64(PBA_XCFG); pxc.fields.reservation_en = (master != 0); pxc.fields.rcv_groupid = group; @@ -304,17 +315,18 @@ pbax_configure(int master, int group, int chip, int group_mask) /// \retval 0 Success /// /// \retval -PBAX_INVALID_OBJECT The \a target parameter is NULL (0) or -/// otherwise invalid. +/// otherwise invalid. /// -/// \retval -PBAX_INVALID_ARGUMENT_TARGET One or more of the arguments +/// \retval -PBAX_INVALID_ARGUMENT_TARGET One or more of the arguments /// is invalid. int pbax_target_create(PbaxTarget* target, - int type, int scope, int queue, + int type, int scope, int queue, int group, int chip_or_group) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(target == 0, PBAX_INVALID_OBJECT); SSX_ERROR_IF(((type != PBAX_UNICAST) && (type != PBAX_BROADCAST)) || ((scope != PBAX_GROUP) && (scope != PBAX_SYSTEM)) || @@ -376,7 +388,7 @@ pbax_target_create(PbaxTarget* target, /// /// \retval -PBAX_TIMEOUT The caller-specified timeout expired before the PBAX /// send machine became free, but the PBAX send machine does not show error -/// status. +/// status. /// /// \retval -PBAX_SEND_ERROR The PBAXSNDSTAT.snd_error bit is asserted. It /// is expected that this error will cause the PBA error interrupt to fire - @@ -391,39 +403,52 @@ _pbax_send(PbaxTarget* target, uint64_t data, SsxInterval timeout) // The PBAX is always polled at least twice to guarantee that we always // poll once after a timeout - unless the caller explicitly requested a 0 - // timeout. - - start = 0; - timed_out = 0; - do { + // timeout. + + start = 0; + timed_out = 0; + + do + { pss.words.high_order = in32(PBA_XSNDSTAT); - if (pss.fields.snd_error) { + + if (pss.fields.snd_error) + { rc = -PBAX_SEND_ERROR; break; } - if (!pss.fields.snd_in_progress) { + + if (!pss.fields.snd_in_progress) + { rc = 0; break; } - if (start == 0) { + + if (start == 0) + { start = ssx_timebase_get(); } - if ((timeout == 0) || timed_out) { + + if ((timeout == 0) || timed_out) + { rc = -PBAX_SEND_TIMEOUT; break; } - timed_out = + + timed_out = ((timeout != SSX_WAIT_FOREVER) && ((ssx_timebase_get() - start) > timeout)); - } while (1); + } + while (1); // Configure the send engine and initiate the write, which is kicked off // by writing the high-order word of the send data register. - if (!rc) { + if (!rc) + { out32(PBA_XSNDTX, target->target.words.high_order); - out32(PBA_XSNDDAT + 4, data & 0xffffffff); - out32(PBA_XSNDDAT, data >> 32); + out32(PBA_XSNDDAT + 4, data >> 32); + out32(PBA_XSNDDAT, data & 0xffffffff); } return rc; @@ -459,21 +484,27 @@ pbax_send(PbaxTarget* target, uint64_t data) int rc; rc = _pbax_send(target, data, PBAX_SEND_DEFAULT_TIMEOUT); - if (rc) { - if (rc == -PBAX_SEND_TIMEOUT) { + + if (rc) + { + if (rc == -PBAX_SEND_TIMEOUT) + { SSX_ERROR(PBAX_SEND_TIMEOUT); - } else { + } + else + { SSX_ERROR(PBAX_SEND_ERROR); } } + return rc; } - - - - + + + + diff --git a/src/ssx/occhw/occhw_pba.h b/src/ssx/occhw/occhw_pba.h index 96272a7..46c6901 100644 --- a/src/ssx/occhw/occhw_pba.h +++ b/src/ssx/occhw/occhw_pba.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -36,11 +36,6 @@ /// \todo Add Doxygen grouping to constant groups -// @TODO - TEMP: Added to eliminate errors: implicit declaration of functions out32 & in32 -// These functions are used in the pbax functions defined below. -#include "ssx_api.h" -#include "ppc32.h" - #include "pba_register_addresses.h" #include "pba_firmware_registers.h" @@ -52,7 +47,7 @@ // It is assumed the the PBA BAR sets will be assigned according to the // following scheme. There are still many open questions concerning PBA -// setup. +// setup. /// The number of PBA Base Address Registers (BARS) #define PBA_BARS 4 @@ -73,8 +68,8 @@ #define PBA_SLAVE_PORE_GPE 0 /* GPE0/1, but only 1 can access mainstore */ #define PBA_SLAVE_OCC 1 /* 405 I- and D-cache */ -#define PBA_SLAVE_PORE_SLW 2 -#define PBA_SLAVE_OCB 3 +#define PBA_SLAVE_PORE_SLW 2 +#define PBA_SLAVE_OCB 3 /// The maximum number of bytes a PBA block-copy engine can transfer at once #define PBA_BCE_SIZE_MAX 4096 @@ -117,10 +112,10 @@ #define PBA_WRITE_TSIZE_CHIPLET(chiplet) (chiplet) -#define PBA_WRITE_TSIZE_ARMW_ADD 0x03 -#define PBA_WRITE_TSIZE_ARMW_AND 0x13 -#define PBA_WRITE_TSIZE_ARMW_OR 0x23 -#define PBA_WRITE_TSIZE_ARMW_XOR 0x33 +#define PBA_WRITE_TSIZE_ARMW_ADD 0x02 +#define PBA_WRITE_TSIZE_ARMW_AND 0x22 +#define PBA_WRITE_TSIZE_ARMW_OR 0x42 +#define PBA_WRITE_TSIZE_ARMW_XOR 0x62 #define PBA_WRITE_TSIZE_DC 0x0 @@ -154,7 +149,7 @@ #define PBA_READ_TTYPE_CI_PR_RD 0x1 /// Cache-inhibited partial read for Centaur getscom(). /// PBA read TTYPE don't care assignment -#define PBA_READ_TTYPE_DC PBA_READ_TTYPE_CL_RD_NC +#define PBA_READ_TTYPE_DC PBA_READ_TTYPE_CL_RD_NC // PBA read prefetch options @@ -164,13 +159,13 @@ #define PBA_READ_PREFETCH_AUTO_LATE 0x2 /// Non-aggressive prefetch /// PBA read prefetch don't care assignment - see gpe_pba_parms_create() -#define PBA_READ_PREFETCH_DC -1 +#define PBA_READ_PREFETCH_DC -1 // PBA PowerBus command scope and priority, and PBA defaults /// Nodal, Local Node -#define POWERBUS_COMMAND_SCOPE_NODAL 0x0 +#define POWERBUS_COMMAND_SCOPE_NODAL 0x0 /// Group, Local 4-chip, (aka, node pump) #define POWERBUS_COMMAND_SCOPE_GROUP 0x1 @@ -183,7 +178,7 @@ /// Foreign, All units on the local chip, local SMP, and remote chip (pivot /// nodes), In P8, only 100 and 101 are valid. -#define POWERBUS_COMMAND_SCOPE_FOREIGN0 0x4 +#define POWERBUS_COMMAND_SCOPE_FOREIGN0 0x4 /// Foreign, All units on the local chip, local SMP, and remote chip (pivot /// nodes), In P8, only 100 and 101 are valid. @@ -207,8 +202,8 @@ /// initialization-only and/or lab-only procedure, so this long polling /// timeout is not a problem. #ifndef PBA_SLAVE_RESET_TIMEOUT -#define PBA_SLAVE_RESET_TIMEOUT SSX_MICROSECONDS(100) -#endif + #define PBA_SLAVE_RESET_TIMEOUT SSX_MICROSECONDS(100) +#endif // PBA Error/Panic codes @@ -229,11 +224,13 @@ /// /// The extended address covers only bits 23:36 of the 50-bit PowerBus address. -typedef union pba_extended_address { +typedef union pba_extended_address +{ uint64_t value; uint32_t word[2]; - struct { + struct + { uint64_t reserved0 : 23; uint64_t extended_address : 14; uint64_t reserved1 : 27; @@ -241,14 +238,11 @@ typedef union pba_extended_address { } pba_extended_address_t; -int +int pba_barset_initialize(int idx, uint64_t base, int log_size); -// @TODO - TEMP: PORE assembly code. to be replace with valid GPE code -/* int _pba_slave_reset(int id, SsxInterval timeout, SsxInterval sleep); -*/ int pba_slave_reset(int id); @@ -268,19 +262,18 @@ pba_slave_reset(int id); #define PBAX_QUEUES 2 /// The number of PBAX Node Ids -#define PBAX_NODES 8 +#define PBAX_GROUPS 16 /// The number of PBAX Chip Ids (and group Ids) #define PBAX_CHIPS 8 -#define PBAX_GROUPS PBAX_CHIPS /// The maximum legal PBAX group mask #define PBAX_GROUP_MASK_MAX 0xff // PBAX Send Message Scope -#define PBAX_GROUP 1 -#define PBAX_SYSTEM 2 +#define PBAX_GROUP 3 +#define PBAX_SYSTEM 5 // PBAX Send Type @@ -290,7 +283,7 @@ pba_slave_reset(int id); // Default timeout for pbax_send() #ifndef PBAX_SEND_DEFAULT_TIMEOUT -#define PBAX_SEND_DEFAULT_TIMEOUT SSX_MICROSECONDS(30) + #define PBAX_SEND_DEFAULT_TIMEOUT SSX_MICROSECONDS(30) #endif /// An abstract target for PBAX send operations @@ -304,7 +297,8 @@ pba_slave_reset(int id); /// For applications that use GPE programs to implement PBAX sends, a pointer /// to this object could also be passed to the GPE program. -typedef struct { +typedef struct +{ /// The abstract target /// @@ -317,7 +311,7 @@ typedef struct { int pbax_target_create(PbaxTarget* target, - int type, int scope, int queue, + int type, int scope, int queue, int node, int chip_or_group); int @@ -340,7 +334,7 @@ pbax_send_enable(void) pxc.words.high_order = in32(PBA_XCFG); pxc.fields.pbax_en = 1; out32(PBA_XCFG, pxc.words.high_order); - + } @@ -354,7 +348,7 @@ pbax_send_disable(void) pxc.words.high_order = in32(PBA_XCFG); pxc.fields.pbax_en = 0; out32(PBA_XCFG, pxc.words.high_order); - + } @@ -368,7 +362,7 @@ pbax_clear_send_error(void) pxc.words.high_order = in32(PBA_XCFG); pxc.fields.snd_reset = 1; out32(PBA_XCFG, pxc.words.high_order); -} +} /// Clear the PBAX receive error condition @@ -381,7 +375,7 @@ pbax_clear_receive_error(void) pxc.words.high_order = in32(PBA_XCFG); pxc.fields.rcv_reset = 1; out32(PBA_XCFG, pxc.words.high_order); -} +} #endif /* __ASSEMBLER__ */ diff --git a/src/ssx/occhw/occhw_scom.c b/src/ssx/occhw/occhw_scom.c index 743d0dc..359a991 100644 --- a/src/ssx/occhw/occhw_scom.c +++ b/src/ssx/occhw/occhw_scom.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -75,7 +75,7 @@ /// SCOM-by-SCOM basis. /// /// \bug Modify getscom/putscom to return the SSX error codes rather than -/// 1-7. +/// 1-7. /// /// \bug Implement and use a generic poll_with_timeout(f, arg, t) @@ -90,7 +90,7 @@ // Common SCOM polling loop with software timeout. The PMC is always polled // at least twice to guarantee that we always poll once after a timeout. -static int +static int poll_scom(SsxInterval timeout) { SsxTimebase start; @@ -99,19 +99,28 @@ poll_scom(SsxInterval timeout) start = ssx_timebase_get(); timed_out = 0; - do { - rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); - if (!rc) { + + do + { + rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); + + if (!rc) + { break; } - if (timed_out) { + + if (timed_out) + { rc = -SCOM_TIMEOUT_ERROR; break; } - timed_out = + + timed_out = ((timeout != SSX_WAIT_FOREVER) && ((ssx_timebase_get() - start) > timeout)); - } while (1); + } + while (1); + return rc; } @@ -145,15 +154,15 @@ poll_scom(SsxInterval timeout) /// \retval -SCOM_TIMEOUT_ERROR The software timeout specified by the \a /// timeout parameter expired before the transaction completed. /// -/// retval -SCOM_PROTOCOL_ERROR_GETSCOM_BUSY The PMC SCOM engine was busy when -/// the call was made. +/// retval -SCOM_PROTOCOL_ERROR_GETSCOM_BUSY The PMC SCOM engine was busy when +/// the call was made. int -_getscom(uint32_t address, uint64_t *data, SsxInterval timeout) +_getscom(uint32_t address, uint64_t* data, SsxInterval timeout) { SsxMachineContext ctx; int rc; - occhw_scom_cmd_t *scom_cmd = &OSD_PTR->scom_cmd; + occhw_scom_cmd_t* scom_cmd = &OSD_PTR->scom_cmd; occhw_scom_status_t scom_status; do @@ -167,8 +176,10 @@ _getscom(uint32_t address, uint64_t *data, SsxInterval timeout) ssx_critical_section_enter(SSX_CRITICAL, &ctx); // Check for a transaction already ongoing - rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); - if (rc) { + rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); + + if (rc) + { ssx_critical_section_exit(&ctx); rc = -SCOM_PROTOCOL_ERROR_GETSCOM_BUSY; break; @@ -208,7 +219,9 @@ _getscom(uint32_t address, uint64_t *data, SsxInterval timeout) } } - }while(0); + } + while(0); + return rc; } @@ -238,35 +251,66 @@ _getscom(uint32_t address, uint64_t *data, SsxInterval timeout) ///\ retval 1-7 A PCB error code. See \c pcb_common.h int -getscom(uint32_t address, uint64_t *data) +getscom(uint32_t address, uint64_t* data) { int rc; rc = _getscom(address, data, SCOM_TIMEOUT); - if (rc == 0) { + + if (rc == 0) + { return 0; } - if ((rc > 0) && (rc <= SCOM_ERROR_LIMIT)) { + if ((rc > 0) && (rc <= SCOM_ERROR_LIMIT)) + { *data = 0; - } else { + } + else + { //printk("getscom(0x%08x, %p) : Failed with error %d\n", // address, data, rc); - if (rc > 0) { - switch (rc) { - case 1: SSX_PANIC(SCOM_PCB_ERROR_1_GETSCOM); break; - case 2: SSX_PANIC(SCOM_PCB_ERROR_2_GETSCOM); break; - case 3: SSX_PANIC(SCOM_PCB_ERROR_3_GETSCOM); break; - case 4: SSX_PANIC(SCOM_PCB_ERROR_4_GETSCOM); break; - case 5: SSX_PANIC(SCOM_PCB_ERROR_5_GETSCOM); break; - case 6: SSX_PANIC(SCOM_PCB_ERROR_6_GETSCOM); break; - default: SSX_PANIC(SCOM_PCB_ERROR_7_GETSCOM); break; - } - } else if (rc == -SCOM_TIMEOUT_ERROR) { + if (rc > 0) + { + switch (rc) + { + case 1: + SSX_PANIC(SCOM_PCB_ERROR_1_GETSCOM); + break; + + case 2: + SSX_PANIC(SCOM_PCB_ERROR_2_GETSCOM); + break; + + case 3: + SSX_PANIC(SCOM_PCB_ERROR_3_GETSCOM); + break; + + case 4: + SSX_PANIC(SCOM_PCB_ERROR_4_GETSCOM); + break; + + case 5: + SSX_PANIC(SCOM_PCB_ERROR_5_GETSCOM); + break; + + case 6: + SSX_PANIC(SCOM_PCB_ERROR_6_GETSCOM); + break; + + default: + SSX_PANIC(SCOM_PCB_ERROR_7_GETSCOM); + break; + } + } + else if (rc == -SCOM_TIMEOUT_ERROR) + { SSX_PANIC(SCOM_TIMEOUT_ERROR_GETSCOM); - } else { + } + else + { SSX_PANIC(SCOM_PROTOCOL_ERROR_GETSCOM); } } @@ -288,7 +332,7 @@ getscom(uint32_t address, uint64_t *data) /// This routine executes in an SSX_CRITICAL critical section. /// /// Unlike most other APIs, this API returns both positive and negative error -/// codes, as well as the 0 code for success. +/// codes, as well as the 0 code for success. /// /// If the transaction experiences a software timeout (controlled by the \a /// timeout parameter) or a protocol error, the PMC PIB master will be left in @@ -302,15 +346,15 @@ getscom(uint32_t address, uint64_t *data) /// \retval -SCOM_TIMEOUT The software timeout specified by the \a timeout /// parameter expired before the transaction completed. /// -/// \retval -SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY The PMC SCOM engine was busy when -/// the call was made. +/// \retval -SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY The PMC SCOM engine was busy when +/// the call was made. int _putscom(uint32_t address, uint64_t data, SsxInterval timeout) { SsxMachineContext ctx; int rc; - occhw_scom_cmd_t *scom_cmd = &OSD_PTR->scom_cmd; + occhw_scom_cmd_t* scom_cmd = &OSD_PTR->scom_cmd; occhw_scom_status_t scom_status; do @@ -324,8 +368,10 @@ _putscom(uint32_t address, uint64_t data, SsxInterval timeout) ssx_critical_section_enter(SSX_CRITICAL, &ctx); // Check for a transaction already ongoing - rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); - if (rc) { + rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); + + if (rc) + { ssx_critical_section_exit(&ctx); rc = -SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY; break; @@ -344,7 +390,7 @@ _putscom(uint32_t address, uint64_t data, SsxInterval timeout) scom_status.status32 = scom_cmd->scom_status.status32; ssx_critical_section_exit(&ctx); - + if(!rc) { //check that the GPE updated the scom status. Normally, @@ -362,7 +408,9 @@ _putscom(uint32_t address, uint64_t data, SsxInterval timeout) rc = scom_status.sibrc; } } - }while(0); + } + while(0); + return rc; } @@ -377,7 +425,7 @@ _putscom(uint32_t address, uint64_t data, SsxInterval timeout) /// This routine executes in an SSX_CRITICAL critical section. /// /// Unlike most other APIs, this API returns positive error -/// codes, as well as the 0 code for success. +/// codes, as well as the 0 code for success. /// /// If the transaction experiences a software timeout (controlled by the \a /// timeout parameter), a protocol error, or a PCB error greater than the @@ -397,26 +445,53 @@ putscom(uint32_t address, uint64_t data) rc = _putscom(address, data, SCOM_TIMEOUT); - if ((rc == 0) || ((rc > 0) && (rc <= SCOM_ERROR_LIMIT))) { + if ((rc == 0) || ((rc > 0) && (rc <= SCOM_ERROR_LIMIT))) + { return rc; } //printk("putscom(0x%08x, 0x%016llx) : Failed with error %d\n", // address, data, rc); - if (rc > 0) { - switch (rc) { - case 1: SSX_PANIC(SCOM_PCB_ERROR_1_PUTSCOM); break; - case 2: SSX_PANIC(SCOM_PCB_ERROR_2_PUTSCOM); break; - case 3: SSX_PANIC(SCOM_PCB_ERROR_3_PUTSCOM); break; - case 4: SSX_PANIC(SCOM_PCB_ERROR_4_PUTSCOM); break; - case 5: SSX_PANIC(SCOM_PCB_ERROR_5_PUTSCOM); break; - case 6: SSX_PANIC(SCOM_PCB_ERROR_6_PUTSCOM); break; - default: SSX_PANIC(SCOM_PCB_ERROR_7_PUTSCOM); break; + if (rc > 0) + { + switch (rc) + { + case 1: + SSX_PANIC(SCOM_PCB_ERROR_1_PUTSCOM); + break; + + case 2: + SSX_PANIC(SCOM_PCB_ERROR_2_PUTSCOM); + break; + + case 3: + SSX_PANIC(SCOM_PCB_ERROR_3_PUTSCOM); + break; + + case 4: + SSX_PANIC(SCOM_PCB_ERROR_4_PUTSCOM); + break; + + case 5: + SSX_PANIC(SCOM_PCB_ERROR_5_PUTSCOM); + break; + + case 6: + SSX_PANIC(SCOM_PCB_ERROR_6_PUTSCOM); + break; + + default: + SSX_PANIC(SCOM_PCB_ERROR_7_PUTSCOM); + break; } - } else if (rc == -SCOM_TIMEOUT_ERROR) { + } + else if (rc == -SCOM_TIMEOUT_ERROR) + { SSX_PANIC(SCOM_TIMEOUT_ERROR_PUTSCOM); - } else { + } + else + { SSX_PANIC(SCOM_PROTOCOL_ERROR_PUTSCOM); } diff --git a/src/ssx/occhw/occhw_scom.h b/src/ssx/occhw/occhw_scom.h index 847fa90..bbf1869 100644 --- a/src/ssx/occhw/occhw_scom.h +++ b/src/ssx/occhw/occhw_scom.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -46,17 +46,17 @@ #ifndef __ASSEMBLER__ -int -_getscom(uint32_t address, uint64_t *data, SsxInterval timeout); + int + _getscom(uint32_t address, uint64_t* data, SsxInterval timeout); -int -getscom(uint32_t address, uint64_t *data); + int + getscom(uint32_t address, uint64_t* data); -int -_putscom(uint32_t address, uint64_t data, SsxInterval timeout); + int + _putscom(uint32_t address, uint64_t data, SsxInterval timeout); -int -putscom(uint32_t address, uint64_t data); + int + putscom(uint32_t address, uint64_t data); #endif /* __ASSEMBLER__ */ @@ -92,7 +92,7 @@ putscom(uint32_t address, uint64_t data); /// The default timeout for getscom()/putscom() /// /// This timeout is enforced by the firmware to guarantee a timeout regardless -/// of the hardware setup. +/// of the hardware setup. /// /// The expectation is that the hardware will be set up to enforce a PCB /// timeout of 8K cycles, or 16.384us @ 500 MHz. A timeout only occurs if @@ -109,7 +109,7 @@ putscom(uint32_t address, uint64_t data); /// (either the setup, hardware or firmware) must be broken. #ifndef SCOM_TIMEOUT -#define SCOM_TIMEOUT SSX_MICROSECONDS(17) + #define SCOM_TIMEOUT SSX_MICROSECONDS(17) #endif @@ -124,7 +124,7 @@ putscom(uint32_t address, uint64_t data); /// well. #ifndef SCOM_ERROR_LIMIT -#define SCOM_ERROR_LIMIT PCB_ERROR_CHIPLET_OFFLINE + #define SCOM_ERROR_LIMIT PCB_ERROR_CHIPLET_OFFLINE #endif #endif // __OCCHW_SCOM_H__ diff --git a/src/ssx/occhw/occhw_sramctl.h b/src/ssx/occhw/occhw_sramctl.h index 7f1b1e5..c8f4604 100644 --- a/src/ssx/occhw/occhw_sramctl.h +++ b/src/ssx/occhw/occhw_sramctl.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/occhw/ssx_port.h b/src/ssx/occhw/ssx_port.h index 81a52aa..eda7c64 100644 --- a/src/ssx/occhw/ssx_port.h +++ b/src/ssx/occhw/ssx_port.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/occhw/ssxocchwfiles.mk b/src/ssx/occhw/ssxocchwfiles.mk index 3559ae7..41417df 100644 --- a/src/ssx/occhw/ssxocchwfiles.mk +++ b/src/ssx/occhw/ssxocchwfiles.mk @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2015 +# Contributors Listed Below - COPYRIGHT 2015,2016 # [+] International Business Machines Corp. # # diff --git a/src/ssx/ppc32/Makefile b/src/ssx/ppc32/Makefile index 67541ac..eb270c7 100644 --- a/src/ssx/ppc32/Makefile +++ b/src/ssx/ppc32/Makefile @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2014,2015 +# Contributors Listed Below - COPYRIGHT 2014,2016 # [+] International Business Machines Corp. # # diff --git a/src/ssx/ppc32/div64.S b/src/ssx/ppc32/div64.S index cc6309b..f8e1b34 100644 --- a/src/ssx/ppc32/div64.S +++ b/src/ssx/ppc32/div64.S @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/ppc32/ppc32.h b/src/ssx/ppc32/ppc32.h index 0ba8a46..af01560 100644 --- a/src/ssx/ppc32/ppc32.h +++ b/src/ssx/ppc32/ppc32.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -58,8 +58,8 @@ /// ssize_t is defined explictly rather than bringing in all of <unistd.h> #ifndef __ssize_t_defined -#define __ssize_t_defined -typedef int ssize_t; + #define __ssize_t_defined + typedef int ssize_t; #endif /// A memory barrier @@ -76,23 +76,28 @@ typedef int ssize_t; /// CouNT Leading Zeros Word #define cntlzw(x) \ -({uint32_t __x = (x); \ - uint32_t __lzw; \ - asm volatile ("cntlzw %0, %1" : "=r" (__lzw) : "r" (__x)); \ - __lzw;}) + ({uint32_t __x = (x); \ + uint32_t __lzw; \ + asm volatile ("cntlzw %0, %1" : "=r" (__lzw) : "r" (__x)); \ + __lzw;}) /// CouNT Leading Zeros : uint32_t static inline int -cntlz32(uint32_t x) { +cntlz32(uint32_t x) +{ return cntlzw(x); } /// CouNT Leading Zeros : uint64_t static inline int -cntlz64(uint64_t x) { - if (x > 0xffffffff) { +cntlz64(uint64_t x) +{ + if (x > 0xffffffff) + { return cntlz32(x >> 32); - } else { + } + else + { return 32 + cntlz32(x); } } @@ -104,7 +109,7 @@ popcount32(uint32_t x) { return __builtin_popcount(x); } - + /// 64-bit population count static inline int @@ -121,27 +126,27 @@ popcount64(uint64_t x) /// 8-bit MMIO Write #define out8(addr, data) \ -do {*(volatile uint8_t *)(addr) = (data); eieio();} while(0) + do {*(volatile uint8_t *)(addr) = (data); eieio();} while(0) /// 8-bit MMIO Read #define in8(addr) \ -({uint8_t __data = *(volatile uint8_t *)(addr); eieio(); __data;}) + ({uint8_t __data = *(volatile uint8_t *)(addr); eieio(); __data;}) /// 16-bit MMIO Write #define out16(addr, data) \ -do {*(volatile uint16_t *)(addr) = (data); eieio();} while(0) + do {*(volatile uint16_t *)(addr) = (data); eieio();} while(0) /// 16-bit MMIO Read #define in16(addr) \ -({uint16_t __data = *(volatile uint16_t *)(addr); eieio(); __data;}) + ({uint16_t __data = *(volatile uint16_t *)(addr); eieio(); __data;}) /// 32-bit MMIO Write #define out32(addr, data) \ -do {*(volatile uint32_t *)(addr) = (data); eieio();} while(0) + do {*(volatile uint32_t *)(addr) = (data); eieio();} while(0) /// 32-bit MMIO Read #define in32(addr) \ -({uint32_t __data = *(volatile uint32_t *)(addr); eieio(); __data;}) + ({uint32_t __data = *(volatile uint32_t *)(addr); eieio(); __data;}) /// 64-bit MMIO Write #define out64(addr, data) \ @@ -178,6 +183,7 @@ do {*(volatile uint32_t *)(addr) = (data); eieio();} while(0) #else // __ASSEMBLER__ /// Store revision information as a global string constant +// *INDENT-OFF* .macro .revision_string, symbol:req, rev:req .pushsection .rodata .balign 4 @@ -187,6 +193,7 @@ do {*(volatile uint32_t *)(addr) = (data); eieio();} while(0) .balign 4 .popsection .endm +// *INDENT-ON* #endif // __ASSEMBLER__ diff --git a/src/ssx/ppc32/ppc32_asm.h b/src/ssx/ppc32/ppc32_asm.h index b681e88..5287806 100644 --- a/src/ssx/ppc32/ppc32_asm.h +++ b/src/ssx/ppc32/ppc32_asm.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -55,11 +55,11 @@ /// absolute or relocatable expression. /// /// Forms: -/// +/// /// \b _lbzi \a dreg, \a areg, \a addr - Load Byte and Zero from Immediate address \n /// \b _lhzi \a dreg, \a areg, \a addr - Load Halfword and Zero from Immediate address \n /// \b _lwzi \a dreg, \a areg, \a addr - Load Word and Zero from Immediate address \n -/// +/// /// /// \section _stxi _st<w,h,b>i - STore register to Immediate address /// @@ -75,7 +75,7 @@ /// absolute or relocatable expression. /// /// Forms: -/// +/// /// \b _stbi \a dreg, \a areg, \a addr - STore Byte to Immediate address \n /// \b _sthi \a dreg, \a areg, \a addr - STore Halfword to Immediate address \n /// \b _stwi \a dreg, \a areg, \a addr - STore Word to Immediate address \n @@ -99,8 +99,8 @@ /// \arg \c addr A 32-bit immediate address, assumed to be a /// relocatable address in one of the small data sections. /// -/// Forms: -/// +/// Forms: +/// /// \b _lbzsd \a dreg, \a addr - Load Byte and Zero from Small Data area \n /// \b _lhzsd \a dreg, \a addr - Load Halfword and Zero from Small Data area \n /// \b _lwzsd \a dreg, \a addr - Load Word and Zero from Small Data area \n @@ -158,8 +158,8 @@ /// \arg \c ra Register containing the counter address at entry /// /// \a rs and \a ra must be unique. At the end of the macro the count -/// is updated to memory and \a ra is unmodified. -/// +/// is updated to memory and \a ra is unmodified. +/// /// /// \section _setclear_bits Set/Clear/Copy Bits from Immediate Positions /// @@ -183,7 +183,7 @@ /// \b _copyfield \a rd, \a rs, \a n, \a b - Copy an n-bit field from \a rs to /// \a rd starting from bit \a b \n /// -/// +/// /// \section pseudo_ops Assembler Pseudo-Ops Macros /// /// Several macros define new 'pseudo-ops'. @@ -209,7 +209,7 @@ /// \b .function \a symbol - Define a local function \a symbol \n /// \b .global_function \a symbol - Define a global function \a symbol \n /// -/// +/// /// \subsection epilogue .epilogue /// /// The \c .epilogue pseudo-op adds size and type information for @@ -225,6 +225,7 @@ /// \cond #ifdef __ASSEMBLER__ +// *INDENT-OFF* ### **************************************************************************** ### _l<b,h,w>zi @@ -239,7 +240,7 @@ lbzu \dreg, \addr@l(\areg) .endif .endm - + .macro _lhzi dreg, areg, addr lis \areg, \addr@ha .ifc \areg, \dreg @@ -248,7 +249,7 @@ lhzu \dreg, \addr@l(\areg) .endif .endm - + .macro _lwzi dreg, areg, addr lis \areg, \addr@ha .ifc \areg, \dreg @@ -265,7 +266,7 @@ lis \areg, \addr@ha stbu \dreg, \addr@l(\areg) .endm - + .macro _sthi dreg, areg, addr .ifc \areg, \dreg .err @@ -273,7 +274,7 @@ lis \areg, \addr@ha sthu \dreg, \addr@l(\areg) .endm - + .macro _stwi dreg, areg, addr .ifc \areg, \dreg .err @@ -419,12 +420,13 @@ .size \symbol, . - \symbol .endm +// *INDENT-ON* #endif /* __ASSEMBLER__ */ /// \endcond - + // Local Variables: // mode:asm // End: - + #endif /* __PPC32_ASM_H__ */ diff --git a/src/ssx/ppc32/ppc32_gcc.c b/src/ssx/ppc32/ppc32_gcc.c index 8fe9bf5..2e20116 100644 --- a/src/ssx/ppc32/ppc32_gcc.c +++ b/src/ssx/ppc32/ppc32_gcc.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -55,16 +55,20 @@ __lshrdi3(uint64_t x, int i) { Uint64 input, result; - if (i == 0) { + if (i == 0) + { return x; } input.value = x; - if (i >= 32) { + if (i >= 32) + { result.word[0] = 0; result.word[1] = input.word[0] >> (i - 32); - } else { + } + else + { result.word[0] = input.word[0] >> i; result.word[1] = (input.word[1] >> i) | (input.word[0] << (32 - i)); } @@ -83,16 +87,20 @@ __ashldi3(uint64_t x, int i) { Uint64 input, result; - if (i == 0) { + if (i == 0) + { return x; } input.value = x; - if (i >= 32) { + if (i >= 32) + { result.word[1] = 0; result.word[0] = input.word[1] << (i - 32); - } else { + } + else + { result.word[1] = input.word[1] << i; result.word[0] = (input.word[0] << i) | (input.word[1] >> (32 - i)); } @@ -112,19 +120,23 @@ __ashrdi3(uint64_t x, int i) { Int64 input, result; - if (i == 0) { + if (i == 0) + { return x; } input.value = x; - if (i >= 32) { + if (i >= 32) + { result.word[0] = input.word[0] >> 31; result.word[1] = input.word[0] >> (i - 32); - } else { + } + else + { result.word[0] = input.word[0] >> i; - result.word[1] = - (((uint32_t)input.word[1]) >> i) | + result.word[1] = + (((uint32_t)input.word[1]) >> i) | (input.word[0] << (32 - i)); } @@ -165,7 +177,7 @@ __popcountdi2(uint64_t x) // 64-bit divides // // For the unsigned case, note that divide by 0 returns quotient = remainder = -// 0. +// 0. // // For the signed case, in general we perform the division on the absolute // values and fix the signs of the quotient and remainder at the end. @@ -181,22 +193,22 @@ __popcountdi2(uint64_t x) // but only 184 bytes as configured here. #if 0 -// For the signed cases, we need to handle the special case that the dividend -// or divisor is the most negative integer. -// -// If the dividend is the most negative integer, then dividing this integer by -// -1 would overflow as a positive quotient, so we set quotient and remainder -// to 0 in this case. For divide by 1, the quotient is the most negative -// integer. Otherwise we adjust the dividend by the absolute value of the -// divisor, then fix up the quotient later by adding or subtracting 1. -// -// If the divisor is the most negative integer, then the quotient is always 0 -// unless the dividend is also the most negative integer, in which case the -// quotient is 1 and the remainder is 0. -// + // For the signed cases, we need to handle the special case that the dividend + // or divisor is the most negative integer. + // + // If the dividend is the most negative integer, then dividing this integer by + // -1 would overflow as a positive quotient, so we set quotient and remainder + // to 0 in this case. For divide by 1, the quotient is the most negative + // integer. Otherwise we adjust the dividend by the absolute value of the + // divisor, then fix up the quotient later by adding or subtracting 1. + // + // If the divisor is the most negative integer, then the quotient is always 0 + // unless the dividend is also the most negative integer, in which case the + // quotient is 1 and the remainder is 0. + // #endif -uint64_t +uint64_t __udivdi3(uint64_t u, uint64_t v) { uint64_t quotient, remainder; @@ -206,7 +218,7 @@ __udivdi3(uint64_t u, uint64_t v) } -uint64_t +uint64_t __umoddi3(uint64_t u, uint64_t v) { uint64_t quotient, remainder; @@ -217,12 +229,12 @@ __umoddi3(uint64_t u, uint64_t v) #if 0 -#define INT64_T_MIN ((int64_t)(0x8000000000000000ull)) + #define INT64_T_MIN ((int64_t)(0x8000000000000000ull)) #endif void -__ppc32_sdiv64(int64_t u, int64_t v, - int64_t *quotient, int64_t *remainder) +__ppc32_sdiv64(int64_t u, int64_t v, + int64_t* quotient, int64_t* remainder) { int q_negate, r_negate; uint64_t uu, uv; @@ -236,47 +248,66 @@ __ppc32_sdiv64(int64_t u, int64_t v, uv = (v < 0 ? -v : v); #if 0 - if (u == INT64_T_MIN) { - if (v == -1) { + + if (u == INT64_T_MIN) + { + if (v == -1) + { *quotient = 0; *remainder = 0; return; - } else if (v == 1) { + } + else if (v == 1) + { *quotient = INT64_T_MIN; *remainder = 0; return; - } else if (v == INT64_T_MIN) { + } + else if (v == INT64_T_MIN) + { *quotient = 1; *remainder = 0; return; - } else { + } + else + { fixup = 1; u += (v < 0 ? -v : v); } - } else if (v == INT64_T_MIN) { + } + else if (v == INT64_T_MIN) + { *quotient = 0; *remainder = u; return; } + #endif - __ppc32_udiv64(uu, uv, (uint64_t *)quotient, (uint64_t *)remainder); + __ppc32_udiv64(uu, uv, (uint64_t*)quotient, (uint64_t*)remainder); #if 0 - if (fixup) { + + if (fixup) + { *quotient += 1; } + #endif - if (q_negate) { + + if (q_negate) + { *quotient = -(*quotient); } - if (r_negate) { + + if (r_negate) + { *remainder = -(*remainder); } } - -int64_t + +int64_t __divdi3(int64_t u, int64_t v) { int64_t quotient, remainder; @@ -286,7 +317,7 @@ __divdi3(int64_t u, int64_t v) } -int64_t +int64_t __moddi3(int64_t u, int64_t v) { int64_t quotient, remainder; @@ -307,25 +338,34 @@ __ucmpdi2(uint64_t i_a, uint64_t i_b) a.value = i_a; b.value = i_b; - if (a.word[0] < b.word[0]) { + if (a.word[0] < b.word[0]) + { rv = 0; - } else if (a.word[0] > b.word[0]) { + } + else if (a.word[0] > b.word[0]) + { rv = 2; - } else if (a.word[1] < b.word[1]) { + } + else if (a.word[1] < b.word[1]) + { rv = 0; - } else if (a.word[1] > b.word[1]) { + } + else if (a.word[1] > b.word[1]) + { rv = 2; - } else { + } + else + { rv = 1; } return rv; } - - - - + + + + diff --git a/src/ssx/ppc32/ppc32_gcc.h b/src/ssx/ppc32/ppc32_gcc.h index 7931fcd..a5cbef2 100644 --- a/src/ssx/ppc32/ppc32_gcc.h +++ b/src/ssx/ppc32/ppc32_gcc.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,14 +40,16 @@ /// A 64-bit unsigned integer type -typedef union { +typedef union +{ uint64_t value; uint32_t word[2]; } Uint64; /// A 64-bit signed integer type -typedef union { +typedef union +{ int64_t value; int32_t word[2]; } Int64; @@ -70,14 +72,14 @@ __popcountdi2(uint64_t x); /// Unsigned 64/64 bit divide, returning quotient and remainder via pointers. void -__ppc32_udiv64(uint64_t u, uint64_t v, uint64_t *q, uint64_t *r); +__ppc32_udiv64(uint64_t u, uint64_t v, uint64_t* q, uint64_t* r); /// Signed 64/64 bit divide, returning quotient and remainder via pointers. void -__ppc32_sdiv64(int64_t u, int64_t v, int64_t *q, int64_t *r); +__ppc32_sdiv64(int64_t u, int64_t v, int64_t* q, int64_t* r); -uint64_t +uint64_t __udivdi3(uint64_t u, uint64_t v); int64_t @@ -86,7 +88,7 @@ __divdi3(int64_t u, int64_t v); int64_t __moddi3(int64_t u, int64_t v); -uint64_t +uint64_t __umoddi3(uint64_t u, uint64_t v); int diff --git a/src/ssx/ppc32/savegpr.S b/src/ssx/ppc32/savegpr.S index 4dbfef0..efc04ac 100644 --- a/src/ssx/ppc32/savegpr.S +++ b/src/ssx/ppc32/savegpr.S @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,6 +40,7 @@ /// code was copied. /// +// *INDENT-OFF* .macro SAVE reg .global _savegpr_\reg @@ -98,3 +99,5 @@ mtlr 0 mr 1,11 blr + +// *INDENT-ON* diff --git a/src/ssx/ppc32/ssxppc32files.mk b/src/ssx/ppc32/ssxppc32files.mk index 7987265..1c0414a 100644 --- a/src/ssx/ppc32/ssxppc32files.mk +++ b/src/ssx/ppc32/ssxppc32files.mk @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2014,2015 +# Contributors Listed Below - COPYRIGHT 2014,2016 # [+] International Business Machines Corp. # # diff --git a/src/ssx/ppc405/Makefile b/src/ssx/ppc405/Makefile index 82391e2..5a25846 100644 --- a/src/ssx/ppc405/Makefile +++ b/src/ssx/ppc405/Makefile @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2014,2015 +# Contributors Listed Below - COPYRIGHT 2014,2016 # [+] International Business Machines Corp. # # diff --git a/src/ssx/ppc405/ppc405.h b/src/ssx/ppc405/ppc405.h index 079831d..a08260c 100644 --- a/src/ssx/ppc405/ppc405.h +++ b/src/ssx/ppc405/ppc405.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -35,7 +35,7 @@ /// \brief PowerPC 405 port header for SSX // The 405 has a 32-byte line and 2-way set associative caches. The cache -// configuration varies by chip/ASIC. +// configuration varies by chip/ASIC. // // Regarding the DCACHE_TAG_MASK, used by dcache_flush_all: The IBM // documentation on the D-cache tag sizes doesn't make any sense to me - it @@ -61,37 +61,37 @@ #ifdef HWMACRO_OCC -#define ICACHE_SIZE (16 * 1024) -#define DCACHE_SIZE (16 * 1024) + #define ICACHE_SIZE (16 * 1024) + #define DCACHE_SIZE (16 * 1024) -#define LOG_ICACHE_SIZE 14 -#define LOG_DCACHE_SIZE 14 + #define LOG_ICACHE_SIZE 14 + #define LOG_DCACHE_SIZE 14 #else -#error "Please define the cache configuration of the processor" + #error "Please define the cache configuration of the processor" #endif // Macros to define where declared code is actually compiled #ifdef __PPC405_C__ -#define IF__PPC405_CORE_C__(x) x -#define UNLESS__PPC405_CORE_C__(x) + #define IF__PPC405_CORE_C__(x) x + #define UNLESS__PPC405_CORE_C__(x) #else -#define IF__PPC405_CORE_C__(x) -#define UNLESS__PPC405_CORE_C__(x) x + #define IF__PPC405_CORE_C__(x) + #define UNLESS__PPC405_CORE_C__(x) x #endif #ifdef __PPC405_IRQ_CORE_C__ -#define IF__PPC405_IRQ_CORE_C__(x) x -#define UNLESS__PPC405_IRQ_CORE_C__(x) + #define IF__PPC405_IRQ_CORE_C__(x) x + #define UNLESS__PPC405_IRQ_CORE_C__(x) #else -#define IF__PPC405_IRQ_CORE_C__(x) -#define UNLESS__PPC405_IRQ_CORE_C__(x) x + #define IF__PPC405_IRQ_CORE_C__(x) + #define UNLESS__PPC405_IRQ_CORE_C__(x) x #endif #ifdef HWMACRO_OCC -#include "occhw.h" + #include "occhw.h" #endif #include "ppc32.h" @@ -106,19 +106,19 @@ #include "ppc405_mmu.h" #ifndef PPC405_IR_SUPPORT -#define PPC405_IR_SUPPORT 1 + #define PPC405_IR_SUPPORT 1 #endif #ifndef PPC405_DR_SUPPORT -#define PPC405_DR_SUPPORT 1 + #define PPC405_DR_SUPPORT 1 #endif #define PPC405_RELOCATION_MODE \ ((PPC405_IR_SUPPORT * MSR_IR) | (PPC405_DR_SUPPORT * MSR_DR)) #ifndef __ASSEMBLER__ -void* -memcpy_real(void* dest, const void* src, size_t n); + void* + memcpy_real(void* dest, const void* src, size_t n); #endif #else /* PPC405_MMU_SUPPORT */ @@ -142,7 +142,7 @@ memcpy_real(void* dest, const void* src, size_t n) /// can override this default. #ifndef EXECUTABLE_FREE_SPACE -#define EXECUTABLE_FREE_SPACE 0 + #define EXECUTABLE_FREE_SPACE 0 #endif #include "ppc405_context.h" @@ -235,7 +235,7 @@ memcpy_real(void* dest, const void* src, size_t n) /// try to help the user interpret what happened based on the TRAP code. #ifndef SSX_PANIC - + #define SSX_PANIC(code) \ do { \ barrier(); \ @@ -256,9 +256,9 @@ memcpy_real(void* dest, const void* src, size_t n) // traps to halt the OCC and freeze the timers. #ifdef __PPC405_CORE_C__ -uint32_t __ssx_panic_save_r3; -uint32_t __ssx_panic_save_dbcr0; -uint32_t __ssx_panic_dbcr0 = DBCR0_EDM | DBCR0_TDE | DBCR0_FT; + uint32_t __ssx_panic_save_r3; + uint32_t __ssx_panic_save_dbcr0; + uint32_t __ssx_panic_dbcr0 = DBCR0_EDM | DBCR0_TDE | DBCR0_FT; #endif #endif // SSX_PANIC @@ -272,7 +272,7 @@ uint32_t __ssx_panic_dbcr0 = DBCR0_EDM | DBCR0_TDE | DBCR0_FT; #define SIMICS_MAGIC_BREAKPOINT asm volatile ("rlwimi 0,0,0,0,0") /// This is the Simics 'magic breakpoint' instruction including a memory -/// barrier. +/// barrier. /// /// Note that the memory barrier guarantees that all variables held in /// registers are flushed to memory before the breakpoint, however this might @@ -282,11 +282,11 @@ uint32_t __ssx_panic_dbcr0 = DBCR0_EDM | DBCR0_TDE | DBCR0_FT; /// form may be preferred so that variable values will be visible in memory. #define SIMICS_MAGIC_BREAKPOINT_BARRIER \ - asm volatile ("rlwimi 0,0,0,0,0" : : : "memory") + asm volatile ("rlwimi 0,0,0,0,0" : : : "memory") #else // __ASSEMBLER__ - +// *INDENT-OFF* /// This is the Simics 'magic breakpoint' instruction. An assembler macro /// form is also provided for use within macros. @@ -309,7 +309,7 @@ uint32_t __ssx_panic_dbcr0 = DBCR0_EDM | DBCR0_TDE | DBCR0_FT; /// would require 10. #ifndef SSX_PANIC - + #define SSX_PANIC(code) _ssx_panic code .macro _ssx_panic, code @@ -324,7 +324,7 @@ uint32_t __ssx_panic_dbcr0 = DBCR0_EDM | DBCR0_TDE | DBCR0_FT; .endm #endif // SSX_PANIC - +// *INDENT-ON* #endif // __ASSEMBLER__ @@ -418,28 +418,35 @@ typedef uint32_t SsxMachineContext; UNLESS__PPC405_CORE_C__(extern) inline int -ssx_interrupt_disable(int priority, SsxMachineContext *context) +ssx_interrupt_disable(int priority, SsxMachineContext* context) { - *context = mfmsr(); +*context = mfmsr(); - if (priority == SSX_NONCRITICAL) { +if (priority == SSX_NONCRITICAL) +{ - wrteei(0); +wrteei(0); - } else if (priority == SSX_CRITICAL) { +} +else if (priority == SSX_CRITICAL) +{ - mtmsr(*context & ~(MSR_EE | MSR_CE)); +mtmsr(*context & ~(MSR_EE | MSR_CE)); - } else if (priority == SSX_SUPERCRITICAL) { +} +else if (priority == SSX_SUPERCRITICAL) +{ - mtmsr(*context & ~(MSR_APE | MSR_WE | MSR_CE | MSR_EE | MSR_ME | - MSR_DWE | MSR_DE)); +mtmsr(*context & ~(MSR_APE | MSR_WE | MSR_CE | MSR_EE | MSR_ME | +MSR_DWE | MSR_DE)); - } else if (SSX_ERROR_CHECK_API) { - SSX_ERROR(SSX_INVALID_ARGUMENT_INTERRUPT); - } +} +else if (SSX_ERROR_CHECK_API) +{ +SSX_ERROR(SSX_INVALID_ARGUMENT_INTERRUPT); +} - return SSX_OK; +return SSX_OK; } @@ -456,15 +463,16 @@ ssx_interrupt_disable(int priority, SsxMachineContext *context) UNLESS__PPC405_CORE_C__(extern) inline int -ssx_machine_context_set(SsxMachineContext *context) +ssx_machine_context_set(SsxMachineContext* context) +{ +if (SSX_ERROR_CHECK_API) { - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF(context == 0, SSX_INVALID_ARGUMENT_CONTEXT_SET); - } +SSX_ERROR_IF(context == 0, SSX_INVALID_ARGUMENT_CONTEXT_SET); +} - mtmsr(*context); +mtmsr(*context); - return SSX_OK; +return SSX_OK; } @@ -481,15 +489,16 @@ ssx_machine_context_set(SsxMachineContext *context) UNLESS__PPC405_CORE_C__(extern) inline int -ssx_machine_context_get(SsxMachineContext *context) +ssx_machine_context_get(SsxMachineContext* context) { - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF(context == 0, SSX_INVALID_ARGUMENT_CONTEXT_GET); - } +if (SSX_ERROR_CHECK_API) +{ +SSX_ERROR_IF(context == 0, SSX_INVALID_ARGUMENT_CONTEXT_GET); +} - *context = mfmsr(); +*context = mfmsr(); - return SSX_OK; +return SSX_OK; } @@ -504,11 +513,11 @@ ssx_machine_context_get(SsxMachineContext *context) /// behind the SP are for the initial subroutine's LR. static inline void -__ssx_stack_create_initial_frame(SsxAddress *stack, size_t *size) \ +__ssx_stack_create_initial_frame(SsxAddress* stack, size_t* size) \ { - *stack -= 8; - *size -= 8; - *((SSX_STACK_TYPE *)(*stack)) = 0; +*stack -= 8; +* size -= 8; +* ((SSX_STACK_TYPE*)(*stack)) = 0; } @@ -524,49 +533,52 @@ __ssx_stack_create_initial_frame(SsxAddress *stack, size_t *size) \ /// definition. For certain tests it's also helpful to look at the two /// interrupt counters as a single 0/non-0 field. -typedef union { +typedef union +{ - uint32_t value; +uint32_t value; - struct { +struct +{ - /// The critical interrupt nesting level. If this field is non-zero, - /// then interrupt priority and preemption rules guarantee that a - /// critical interrupt handler is running, and the \c irq field will - /// contain the SsxIrqId of the currently active critical interrupt. - unsigned critical_interrupts : 8; +/// The critical interrupt nesting level. If this field is non-zero, +/// then interrupt priority and preemption rules guarantee that a +/// critical interrupt handler is running, and the \c irq field will +/// contain the SsxIrqId of the currently active critical interrupt. +unsigned critical_interrupts : 8; - /// The non-critical interrupt nesting level. If this field is - /// non-zero and the \c critical_interrupts field is 0, then interrupt - /// priority and preemption rules guarantee that a noncritical - /// interrupt handler is running, and the \c irq field will contain - /// the SsxIrqId of the currently active noncritical interrupt. - unsigned noncritical_interrupts : 8; +/// The non-critical interrupt nesting level. If this field is +/// non-zero and the \c critical_interrupts field is 0, then interrupt +/// priority and preemption rules guarantee that a noncritical +/// interrupt handler is running, and the \c irq field will contain +/// the SsxIrqId of the currently active noncritical interrupt. +unsigned noncritical_interrupts : 8; - /// The SsxIrqId of the currently running (or last run) handler. If - /// either of the interrupt nesting levels are non-0, then this is the - /// SsxIrqId of the IRQ that is currently executing. - unsigned irq : 8; +/// The SsxIrqId of the currently running (or last run) handler. If +/// either of the interrupt nesting levels are non-0, then this is the +/// SsxIrqId of the IRQ that is currently executing. +unsigned irq : 8; - /// A flag indicating that SSX is in thread mode after a call of - /// ssx_start_threads(). - unsigned thread_mode : 1; +/// A flag indicating that SSX is in thread mode after a call of +/// ssx_start_threads(). +unsigned thread_mode : 1; - /// The priority of the currently running thread. In an interrupt - /// context, this is the priority of the thread that was interrupted. - unsigned thread_priority : 7; +/// The priority of the currently running thread. In an interrupt +/// context, this is the priority of the thread that was interrupted. +unsigned thread_priority : 7; - } fields; +} fields; - struct { +struct +{ - /// Used as a 0/non-0 flag for interrupt context. - unsigned interrupt_context : 16; +/// Used as a 0/non-0 flag for interrupt context. +unsigned interrupt_context : 16; - /// Ignore - unsigned ignore : 16; +/// Ignore +unsigned ignore : 16; - } merged_fields; +} merged_fields; } __SsxKernelContext; @@ -627,7 +639,7 @@ typedef union { __ctx.value = mfspr(SPRN_USPRG0); \ __ctx.fields.noncritical_interrupts; }) - + /// Return the critical interrupt nesting level #define __ssx_critical_level() \ @@ -635,7 +647,7 @@ typedef union { __SsxKernelContext __ctx; \ __ctx.value = mfspr(SPRN_USPRG0); \ __ctx.fields.critical_interrupts; }) - + // SSX requires the port to define the type SsxThreadQueue, which is a // priority queue (where 0 is the highest priority). This queue must be able @@ -653,46 +665,46 @@ typedef union { // cntlzw(). static inline void -__ssx_thread_queue_clear(volatile SsxThreadQueue *queue) +__ssx_thread_queue_clear(volatile SsxThreadQueue* queue) { - *queue = 0; +*queue = 0; } static inline void -__ssx_thread_queue_insert(volatile SsxThreadQueue *queue, SsxThreadPriority priority) +__ssx_thread_queue_insert(volatile SsxThreadQueue* queue, SsxThreadPriority priority) { - *queue |= (0x80000000u >> priority); +*queue |= (0x80000000u >> priority); } static inline void -__ssx_thread_queue_delete(volatile SsxThreadQueue *queue, SsxThreadPriority priority) +__ssx_thread_queue_delete(volatile SsxThreadQueue* queue, SsxThreadPriority priority) { - *queue &= ~(0x80000000u >> priority); +*queue &= ~(0x80000000u >> priority); } static inline SsxThreadPriority -__ssx_thread_queue_min(volatile SsxThreadQueue *queue) +__ssx_thread_queue_min(volatile SsxThreadQueue* queue) { - return cntlzw(*queue); +return cntlzw(*queue); } static inline int -__ssx_thread_queue_member(volatile SsxThreadQueue *queue, SsxThreadPriority priority) +__ssx_thread_queue_member(volatile SsxThreadQueue* queue, SsxThreadPriority priority) { - return ((*queue >> (31 - priority)) & 1); +return ((*queue >> (31 - priority)) & 1); } static inline void -__ssx_thread_queue_union(volatile SsxThreadQueue *queue0, - volatile SsxThreadQueue *queue1) +__ssx_thread_queue_union(volatile SsxThreadQueue* queue0, +volatile SsxThreadQueue* queue1) { - *queue0 |= *queue1; +*queue0 |= *queue1; } static inline int -__ssx_thread_queue_count(volatile SsxThreadQueue* queue) +__ssx_thread_queue_count(volatile SsxThreadQueue* queue) { - return __builtin_popcount(*queue); +return __builtin_popcount(*queue); } @@ -759,7 +771,7 @@ __ssx_thread_queue_count(volatile SsxThreadQueue* queue) /// that the CODE_BREAKPOINT is ignored by the Simics PPC405 model as it does /// not model debug events. -#if defined(SIMICS_ENVIRONMENT) && (SIMICS_ENVIRONMENT != 0) +#if defined(SIMICS_ENVIRONMENT) && (SIMICS_ENVIRONMENT != 0) #define CODE_BREAKPOINT \ do { \ if (_code_breakpoint_enable) { \ diff --git a/src/ssx/ppc405/ppc405_boot.S b/src/ssx/ppc405/ppc405_boot.S index 7ffe7dd..9528f44 100644 --- a/src/ssx/ppc405/ppc405_boot.S +++ b/src/ssx/ppc405/ppc405_boot.S @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/ppc405/ppc405_breakpoint.S b/src/ssx/ppc405/ppc405_breakpoint.S index ce3aef2..bcf1783 100644 --- a/src/ssx/ppc405/ppc405_breakpoint.S +++ b/src/ssx/ppc405/ppc405_breakpoint.S @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -33,7 +33,7 @@ /// /// The operation of these short assembler routines is introduced as part of /// the documentation for the CODE_BREAKPOINT macro. - +// *INDENT-OFF* .nolist #include "ssx.h" .list @@ -122,4 +122,5 @@ _code_breakpoint_epilogue: .epilogue _code_breakpoint_epilogue +// *INDENT-ON* /// \endcond diff --git a/src/ssx/ppc405/ppc405_cache.h b/src/ssx/ppc405/ppc405_cache.h index 2d78425..3426e3d 100644 --- a/src/ssx/ppc405/ppc405_cache.h +++ b/src/ssx/ppc405/ppc405_cache.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -36,7 +36,7 @@ /// /// The data cache flush/invalidate macros defined here create a compiler /// memory barrier that will cause GCC to flush/invalidate all memory data -/// held in registers before the macro. +/// held in registers before the macro. #ifndef __ASSEMBLER__ @@ -75,7 +75,7 @@ /// Instruction Cache Block Touch #define icbt(p) asm volatile ("icbt 0, %0" : : "r" (p) : "memory") -void +void icache_invalidate_all(void); void @@ -85,10 +85,10 @@ void dcache_flush_all(void); void -dcache_invalidate(void *p, size_t bytes); +dcache_invalidate(void* p, size_t bytes); void -dcache_flush(void *p, size_t bytes); +dcache_flush(void* p, size_t bytes); /// Invalidate a line in the D-cache /// @@ -104,7 +104,7 @@ dcache_flush(void *p, size_t bytes); /// This API always issues a sync() after the invalidation. static inline void -dcache_invalidate_line(void *p) +dcache_invalidate_line(void* p) { dcbi(p); sync(); @@ -124,7 +124,7 @@ dcache_invalidate_line(void *p) /// This API always issues a sync() after the flush. static inline void -dcache_flush_line(void *p) +dcache_flush_line(void* p) { dcbf(p); sync(); diff --git a/src/ssx/ppc405/ppc405_cache_core.c b/src/ssx/ppc405/ppc405_cache_core.c index 36056e2..2dcac45 100644 --- a/src/ssx/ppc405/ppc405_cache_core.c +++ b/src/ssx/ppc405/ppc405_cache_core.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -30,7 +30,7 @@ /// \file ppc405_cache_core.c /// \brief Core cache management routines required of any PPC405 configuration -/// of SSX that interacts with DMA devices using cacheable memory. +/// of SSX that interacts with DMA devices using cacheable memory. /// /// The entry points in this file are considered 'core' routines that will /// always be present at runtime in any SSX application. @@ -64,27 +64,33 @@ /// dcache_invalidate_line() rather than this API. void -dcache_invalidate(void *p, size_t bytes) +dcache_invalidate(void* p, size_t bytes) { size_t lines; - if (bytes != 0) { + if (bytes != 0) + { lines = 1; - bytes -= + bytes -= MIN((CACHE_LINE_SIZE - ((unsigned long)p % CACHE_LINE_SIZE)), bytes); lines += bytes / CACHE_LINE_SIZE; - if (!cache_aligned(bytes)) { + + if (!cache_aligned(bytes)) + { lines++; } - while (lines--) { + + while (lines--) + { dcbi(p); p += CACHE_LINE_SIZE; } } + sync(); } - + /// Flush and invalidate a range of addresses from the D-cache /// @@ -109,29 +115,35 @@ dcache_invalidate(void *p, size_t bytes) void -dcache_flush(void *p, size_t bytes) +dcache_flush(void* p, size_t bytes) { size_t lines; - if (bytes != 0) { + if (bytes != 0) + { lines = 1; - bytes -= + bytes -= MIN((CACHE_LINE_SIZE - ((unsigned long)p % CACHE_LINE_SIZE)), bytes); lines += bytes / CACHE_LINE_SIZE; - if (!cache_aligned(bytes)) { + + if (!cache_aligned(bytes)) + { lines++; } - while (lines--) { + + while (lines--) + { dcbf(p); p += CACHE_LINE_SIZE; } } + sync(); } - - - + + + diff --git a/src/ssx/ppc405/ppc405_cache_init.S b/src/ssx/ppc405/ppc405_cache_init.S index a8ef79c..e6897f8 100644 --- a/src/ssx/ppc405/ppc405_cache_init.S +++ b/src/ssx/ppc405/ppc405_cache_init.S @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/ppc405/ppc405_context.h b/src/ssx/ppc405/ppc405_context.h index a820a99..9335723 100644 --- a/src/ssx/ppc405/ppc405_context.h +++ b/src/ssx/ppc405/ppc405_context.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -44,22 +44,23 @@ /// exiting the critical section. /// /// \arg \c priority Either \c SSX_CRITICAL, \c SSX_NON_CRITICAL or -/// SSX_SUPERCRITICAL (for \c ssx_critical_section_enter). +/// SSX_SUPERCRITICAL (for \c ssx_critical_section_enter). /// /// \arg \c ctxreg A register that will hold (holds) the machine context (MSR) /// prior to entering the critical section (to be restored) for \c /// _ssx_critical_section_enter (\c _ssx_critical_section_exit). /// /// \arg \c scrreg A scratch register required for the computation of -/// \c _ssx_critical_section_enter. +/// \c _ssx_critical_section_enter. /// /// Forms: -/// +/// /// \b _ssx_critical_section_enter \a priority, \a ctxreg, \a scrreg - Enter a /// critical section \n /// \b _ssx_critical_section_exit \a ctxreg - Exit a critical section #ifdef __ASSEMBLER__ +// *INDENT-OFF* .set _msr_ee_bit, MSR_EE_BIT .set _msr_ce_bit, MSR_CE_BIT @@ -86,7 +87,7 @@ mtmsr \ctxreg isync .endm - + // **************************************************************************** // SSX context save/restore macros for 32-bit Embedded PowerPC // **************************************************************************** @@ -309,7 +310,7 @@ sync # HW239446! #endif mfsprg0 %r3 - + .endif stwu %r1, -SSX_FAST_CTX_SIZE(%r1) # May be corrupted w/o HW239446 @@ -330,7 +331,7 @@ .macro _ssx_fast_ctx_pop - + lwz %r3, SSX_FAST_CTX_CR(%r1) lwz %r4, SSX_FAST_CTX_LR(%r1) @@ -484,7 +485,7 @@ stwu %r1, -SSX_NON_VOL_CTX_SIZE(%r1) stmw %r14, SSX_NON_VOL_CTX_GPR14(%r1) - + .endm @@ -495,6 +496,7 @@ .endm +// *INDENT-ON* #else /* __ASSEMBLER__ */ /// SSX thread context layout as a C structure. @@ -502,7 +504,8 @@ /// This is the structure of the stack area pointed to by /// thread->saved_stack_pointer when a thread is fully context-switched out. -typedef struct { +typedef struct +{ uint32_t r1_nv; uint32_t link_nv; @@ -558,7 +561,8 @@ typedef struct { /// layout of the stack area pointed to by either __ssx_saved_sp_noncritical /// or __ssx_saved_sp_critical. -typedef struct { +typedef struct +{ uint32_t r1_vf; uint32_t link_vf; @@ -594,7 +598,8 @@ typedef struct { /// layout of the stack area pointed to by R1 - unless the fast-mode interrupt /// handler extends the stack. -typedef struct { +typedef struct +{ uint32_t r1; uint32_t link_fast; diff --git a/src/ssx/ppc405/ppc405_core.c b/src/ssx/ppc405/ppc405_core.c index c3a82d3..e1beea2 100644 --- a/src/ssx/ppc405/ppc405_core.c +++ b/src/ssx/ppc405/ppc405_core.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -30,7 +30,7 @@ /// \file ppc405_core.c /// \brief The final bits of SSX runtime code required to complete the PPC405 -/// port. +/// port. /// /// The entry points in this file are considered 'core' routines that will /// always be present during runtime in any SSX application. @@ -58,7 +58,7 @@ typedef union SsxTimebase ssx_ext_timebase_get(void) { SsxExtTimebase snapshot; - volatile SsxExtTimebase *cur_tb = (SsxExtTimebase*)&ppc405_64bit_ext_timebase; + volatile SsxExtTimebase* cur_tb = (SsxExtTimebase*)&ppc405_64bit_ext_timebase; uint32_t tbr; uint32_t high; @@ -72,9 +72,10 @@ SsxTimebase ssx_ext_timebase_get(void) do { snapshot.tbu = cur_tb->tbu; - snapshot.tbl = cur_tb->tbl; + snapshot.tbl = cur_tb->tbl; high = cur_tb->tbu; - }while(snapshot.tbu != high); + } + while(snapshot.tbu != high); //Now read the external timebase register tbr = in32(OCB_OTBR); @@ -84,6 +85,7 @@ SsxTimebase ssx_ext_timebase_get(void) { snapshot.tbu++; } + snapshot.tbl = tbr; return snapshot.tb64; } @@ -96,16 +98,18 @@ SsxTimebase ssx_ext_timebase_get(void) /// \e right \e now is to call this API from a critical section. SsxTimebase -ssx_timebase_get(void) +ssx_timebase_get(void) { Uint64 tb; uint32_t high; - do { + do + { tb.word[0] = mftbu(); tb.word[1] = mftb(); high = mftbu(); - } while (high != tb.word[0]); + } + while (high != tb.word[0]); return tb.value; } @@ -117,7 +121,7 @@ ssx_timebase_get(void) /// what may happen when time warps as a result of this call. void -ssx_timebase_set(SsxTimebase timebase) +ssx_timebase_set(SsxTimebase timebase) { SsxMachineContext ctx; Uint64 tb; @@ -132,7 +136,7 @@ ssx_timebase_set(SsxTimebase timebase) ssx_critical_section_exit(&ctx); } - + /// Enable interrupt preemption /// @@ -150,24 +154,28 @@ ssx_timebase_set(SsxTimebase timebase) /// \retval 0 Successful completion /// /// \retval -SSX_ILLEGAL_CONTEXT The API call was not made from an interrupt -/// context. +/// context. int ssx_interrupt_preemption_enable() { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_UNLESS_ANY_INTERRUPT_CONTEXT(); } - if (__ssx_kernel_context_noncritical_interrupt()) { + if (__ssx_kernel_context_noncritical_interrupt()) + { wrteei(1); - } else { + } + else + { or_msr(MSR_CE); } return SSX_OK; } - + /// Disable interrupt preemption /// @@ -181,24 +189,28 @@ ssx_interrupt_preemption_enable() /// \retval 0 Successful completion /// /// \retval -SSX_ILLEGAL_CONTEXT The API call was not made from an interrupt -/// context. +/// context. int ssx_interrupt_preemption_disable() { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_UNLESS_ANY_INTERRUPT_CONTEXT(); } - if (__ssx_kernel_context_noncritical_interrupt()) { + if (__ssx_kernel_context_noncritical_interrupt()) + { wrteei(0); - } else { + } + else + { andc_msr(MSR_CE); } return SSX_OK; } - + #if SSX_TIMER_SUPPORT @@ -221,15 +233,21 @@ __ssx_schedule_hardware_timeout(SsxTimebase timeout) SsxTimebase now; uint32_t pit; - if (timeout != SSX_TIMEBASE_MAX) { + if (timeout != SSX_TIMEBASE_MAX) + { now = ssx_timebase_get(); - if (timeout <= now) { + if (timeout <= now) + { pit = 1; - } else if ((timeout - now) > 0xffffffff) { + } + else if ((timeout - now) > 0xffffffff) + { pit = 0xffffffff; - } else { + } + else + { pit = timeout - now; } diff --git a/src/ssx/ppc405/ppc405_dcr.h b/src/ssx/ppc405/ppc405_dcr.h index b7e6207..6355101 100644 --- a/src/ssx/ppc405/ppc405_dcr.h +++ b/src/ssx/ppc405/ppc405_dcr.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,9 +42,9 @@ /// Note that \a dcrn must be a compile-time constant. #define mfdcr(dcrn) \ - ({uint32_t __value; \ - asm volatile ("mfdcr %0, %1" : "=r" (__value) : "i" (dcrn)); \ - __value;}) + ({uint32_t __value; \ + asm volatile ("mfdcr %0, %1" : "=r" (__value) : "i" (dcrn)); \ + __value;}) /// Move to DCR @@ -52,10 +52,10 @@ /// Note that \a dcrn must be a compile-time constant. #define mtdcr(dcrn, value) \ - ({uint32_t __value = (value); \ - asm volatile ("mtdcr %0, %1" : : "i" (dcrn), "r" (__value)); \ - }) - + ({uint32_t __value = (value); \ + asm volatile ("mtdcr %0, %1" : : "i" (dcrn), "r" (__value)); \ + }) + /// Read-Modify-Write a DCR with OR (Set DCR bits) /// diff --git a/src/ssx/ppc405/ppc405_exceptions.S b/src/ssx/ppc405/ppc405_exceptions.S index aae7c0b..6c1e685 100644 --- a/src/ssx/ppc405/ppc405_exceptions.S +++ b/src/ssx/ppc405/ppc405_exceptions.S @@ -65,6 +65,7 @@ /// has something similar to a PgP or 405 ASIC interrupt controller. /// /// \cond +// *INDENT-OFF* .nolist #include "ssx.h" @@ -859,4 +860,5 @@ __vectors_2000: __debug_interrupt: b debug_handler +// *INDENT-ON* /// \endcond diff --git a/src/ssx/ppc405/ppc405_init.c b/src/ssx/ppc405/ppc405_init.c index 8405a4a..072a1ed 100644 --- a/src/ssx/ppc405/ppc405_init.c +++ b/src/ssx/ppc405/ppc405_init.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -49,8 +49,9 @@ __ppc405_system_setup() // Initialize the interrupt vectors. - for (irq = 0; irq < EXTERNAL_IRQS; irq++) { - __ppc405_irq_handlers[irq].handler = __ppc405_default_irq_handler; + for (irq = 0; irq < EXTERNAL_IRQS; irq++) + { + __ppc405_irq_handlers[irq].handler = __ppc405_default_irq_handler; __ppc405_irq_handlers[irq].arg = 0; } @@ -78,7 +79,7 @@ __ppc405_system_setup() #if SSX_TIMER_SUPPORT #if SSX_TRACE_SUPPORT -extern SsxTraceBuffer g_ssx_trace_buf; + extern SsxTraceBuffer g_ssx_trace_buf; //set the instance id g_ssx_trace_buf.instance_id = OCCHW_INST_ID_PPC; #endif /* SSX_TRACE_SUPPORT */ diff --git a/src/ssx/ppc405/ppc405_irq.h b/src/ssx/ppc405/ppc405_irq.h index 0ffd2c1..dc0890d 100644 --- a/src/ssx/ppc405/ppc405_irq.h +++ b/src/ssx/ppc405/ppc405_irq.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -73,39 +73,39 @@ // would most likely be a branch to an application-defined handler. #ifndef PPC405_MACHINE_CHECK_HANDLER -#define PPC405_MACHINE_CHECK_HANDLER SSX_PANIC(0x0200) + #define PPC405_MACHINE_CHECK_HANDLER SSX_PANIC(0x0200) #endif #ifndef PPC405_DATA_STORAGE_HANDLER -#define PPC405_DATA_STORAGE_HANDLER SSX_PANIC(0x0300) + #define PPC405_DATA_STORAGE_HANDLER SSX_PANIC(0x0300) #endif #ifndef PPC405_INSTRUCTION_STORAGE_HANDLER -#define PPC405_INSTRUCTION_STORAGE_HANDLER SSX_PANIC(0x0400) + #define PPC405_INSTRUCTION_STORAGE_HANDLER SSX_PANIC(0x0400) #endif #ifndef PPC405_ALIGNMENT_HANDLER -#define PPC405_ALIGNMENT_HANDLER SSX_PANIC(0x0600) + #define PPC405_ALIGNMENT_HANDLER SSX_PANIC(0x0600) #endif #ifndef PPC405_PROGRAM_HANDLER -#define PPC405_PROGRAM_HANDLER SSX_PANIC(0x0700) + #define PPC405_PROGRAM_HANDLER SSX_PANIC(0x0700) #endif #ifndef PPC405_FPU_UNAVAILABLE_HANDLER -#define PPC405_FPU_UNAVAILABLE_HANDLER SSX_PANIC(0x0800) + #define PPC405_FPU_UNAVAILABLE_HANDLER SSX_PANIC(0x0800) #endif #ifndef PPC405_APU_UNAVAILABLE_HANDLER -#define PPC405_APU_UNAVAILABLE_HANDLER SSX_PANIC(0x0f20) + #define PPC405_APU_UNAVAILABLE_HANDLER SSX_PANIC(0x0f20) #endif #ifndef PPC405_DATA_TLB_MISS_HANDLER -#define PPC405_DATA_TLB_MISS_HANDLER SSX_PANIC(0x1100) + #define PPC405_DATA_TLB_MISS_HANDLER SSX_PANIC(0x1100) #endif #ifndef PPC405_INSTRUCTION_TLB_MISS_HANDLER -#define PPC405_INSTRUCTION_TLB_MISS_HANDLER SSX_PANIC(0x1200) + #define PPC405_INSTRUCTION_TLB_MISS_HANDLER SSX_PANIC(0x1200) #endif @@ -122,7 +122,7 @@ /// its own interrupt status . /// \arg \c priority - One of the values \c SSX_CRITICAL or \c /// SSX_NONCRITICAL; to enable a generic handler to choose -/// a behavior appropriate for the interrupt priority. +/// a behavior appropriate for the interrupt priority. typedef void (*SsxIrqHandler)(void* arg, SsxIrqId irq, @@ -168,7 +168,7 @@ void* __ppc405_fit_arg; int -ppc405_watchdog_setup(int tcr_wp, int tcr_wrc, +ppc405_watchdog_setup(int tcr_wp, int tcr_wrc, SsxIrqHandler handler, void* arg); @@ -212,7 +212,7 @@ void* __ppc405_debug_arg; // straightforward solution. The only way that I was able to find to get // naked assembly code into the output stream is to use 'asm' with simple // strings - I couldn't make it work with any kind of argument, as 'asm' would -// reinterpret the arguments and resulting assembler code in various ways. +// reinterpret the arguments and resulting assembler code in various ways. // // There is another alternative that I tried wherby I created a subroutine // call and then filled in the subroutine body with 'asm' code. However, the @@ -243,17 +243,17 @@ void* __ppc405_debug_arg; /// The code stream injected into the GCC assembler output in response to /// /// SSX_IRQ_FAST2FULL(fast_handler, full_handler) -/// +/// /// is (comments added for clarification) : /// /// \code -/// .text -/// .global fast_handler +/// .text +/// .global fast_handler /// .align 5 # Hard-coded PPC405 cache-line alignment -/// fast_handler = . # Can't macro expand LABEL: - this is equivalent -/// bl __ssx_irq_fast2full # The fast-mode to full-mode conversion sequence -/// bl full_handler -/// b __ssx_irq_full_mode_exit +/// fast_handler = . # Can't macro expand LABEL: - this is equivalent +/// bl __ssx_irq_fast2full # The fast-mode to full-mode conversion sequence +/// bl full_handler +/// b __ssx_irq_full_mode_exit /// \endcode /// /// The macro also declares the prototype of the fast handler: @@ -268,13 +268,13 @@ void* __ppc405_debug_arg; __SSX_IRQ_FAST2FULL(.global fast_handler, fast_handler = ., bl full_handler) #define __SSX_IRQ_FAST2FULL(global, label, call) \ -asm(".text"); \ -asm(#global); \ -asm(".align 5"); \ -asm(#label); \ -asm("bl __ssx_irq_fast2full"); \ -asm(#call); \ -asm("b __ssx_irq_full_mode_exit"); + asm(".text"); \ + asm(#global); \ + asm(".align 5"); \ + asm(#label); \ + asm("bl __ssx_irq_fast2full"); \ + asm(#call); \ + asm("b __ssx_irq_full_mode_exit"); #endif /* __ASSEMBLER__ */ @@ -282,7 +282,7 @@ asm("b __ssx_irq_full_mode_exit"); // correct order. We need to bring in the system IRQ header here. #ifdef HWMACRO_OCC -#include "occhw_irq.h" + #include "occhw_irq.h" #endif /// \page ppc405_irq_macros_page PPC405 SSX IRQ Assembler Macros @@ -317,6 +317,7 @@ asm("b __ssx_irq_full_mode_exit"); /// \cond #ifdef __ASSEMBLER__ +// *INDENT-OFF* .macro _ssx_irq_fast2full full_handler bl __ssx_irq_fast2full @@ -324,10 +325,11 @@ asm("b __ssx_irq_full_mode_exit"); b __ssx_irq_full_mode_exit .endm +// *INDENT-ON* #endif /* __ASSEMBLER__ */ /// \endcond - + #ifndef __ASSEMBLER__ @@ -336,9 +338,10 @@ asm("b __ssx_irq_full_mode_exit"); /// to this structure will need to be reflected down into the interrupt /// dispatch assembler code. -typedef struct { - SsxIrqHandler handler; - void *arg; +typedef struct +{ +SsxIrqHandler handler; +void* arg; } Ppc405IrqHandler; @@ -358,7 +361,7 @@ Ppc405IrqHandler __ppc405_irq_handlers[EXTERNAL_IRQS]; UNLESS__PPC405_IRQ_CORE_C__(extern) Ppc405IrqHandler __ppc405_phantom_irq; - + #endif /* __ASSEMBLER__ */ #endif /* __PPC405_IRQ_H__ */ diff --git a/src/ssx/ppc405/ppc405_irq_core.c b/src/ssx/ppc405/ppc405_irq_core.c index ce1c924..4802253 100644 --- a/src/ssx/ppc405/ppc405_irq_core.c +++ b/src/ssx/ppc405/ppc405_irq_core.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -44,8 +44,8 @@ /// This function is installed by default for interrupts not explicitly set up /// by the application. These interrupts should never fire. -void -__ppc405_default_irq_handler(void *arg, +void +__ppc405_default_irq_handler(void* arg, SsxIrqId irq, int critical) { @@ -60,12 +60,12 @@ __ppc405_default_irq_handler(void *arg, /// 'glitch' occurred on the external noncritical or critical interrupt input /// to the PPC405 core. -void __ppc405_phantom_irq_handler(void *arg, +void __ppc405_phantom_irq_handler(void* arg, SsxIrqId irq, int critical) { SSX_PANIC(PPC405_PHANTOM_INTERRUPT); } - + #undef __PPC405_IRQ_CORE_C__ diff --git a/src/ssx/ppc405/ppc405_irq_init.c b/src/ssx/ppc405/ppc405_irq_init.c index 321d238..04779a7 100644 --- a/src/ssx/ppc405/ppc405_irq_init.c +++ b/src/ssx/ppc405/ppc405_irq_init.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -45,7 +45,7 @@ /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_ARGUMENT_PPC405_FIT The \a tcr_fp argument was +/// \retval -SSX_INVALID_ARGUMENT_PPC405_FIT The \a tcr_fp argument was /// invalid when called with a non-null (non-0) \a handler. // Since the SSX_CRITICAL Watchdog interrupt is also controlled by the TCR, we @@ -57,7 +57,8 @@ ppc405_fit_setup(int tcr_fp, SsxIrqHandler handler, void* arg) SsxMachineContext ctx; Ppc405TCR tcr; - if (SSX_ERROR_CHECK_API && handler) { + if (SSX_ERROR_CHECK_API && handler) + { SSX_ERROR_IF((tcr_fp < 0) || (tcr_fp > 3), SSX_INVALID_ARGUMENT_PPC405_FIT); @@ -67,7 +68,8 @@ ppc405_fit_setup(int tcr_fp, SsxIrqHandler handler, void* arg) tcr.value = mfspr(SPRN_TCR); - if (handler) { + if (handler) + { tcr.fields.fp = tcr_fp; tcr.fields.fie = 1; @@ -75,7 +77,9 @@ ppc405_fit_setup(int tcr_fp, SsxIrqHandler handler, void* arg) __ppc405_fit_routine = handler; __ppc405_fit_arg = arg; - } else { + } + else + { tcr.fields.fie = 0; } @@ -87,7 +91,7 @@ ppc405_fit_setup(int tcr_fp, SsxIrqHandler handler, void* arg) return SSX_OK; } - + /// Set up a PPC405 Watchdog interrupt handler /// @@ -98,17 +102,18 @@ ppc405_fit_setup(int tcr_fp, SsxIrqHandler handler, void* arg) /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_ARGUMENT_PPC405_WATCHDOG One or more of the \a tcr_wp +/// \retval -SSX_INVALID_ARGUMENT_PPC405_WATCHDOG One or more of the \a tcr_wp /// or \a tcr_wrc arguments were invalid. int -ppc405_watchdog_setup(int tcr_wp, int tcr_wrc, +ppc405_watchdog_setup(int tcr_wp, int tcr_wrc, SsxIrqHandler handler, void* arg) { SsxMachineContext ctx; Ppc405TCR tcr; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((tcr_wp < 0) || (tcr_wp > 3) || (tcr_wrc < 0) || @@ -125,11 +130,12 @@ ppc405_watchdog_setup(int tcr_wp, int tcr_wrc, tcr.fields.wp = tcr_wp; tcr.fields.wrc = tcr_wrc; - if (handler == 0) { + if (handler == 0) + { // Reinstall the default handler and clear the interrupt enable. Then // clear any pending interrupt status. - // WIS. + // WIS. __ppc405_watchdog_routine = __ppc405_default_irq_handler; __ppc405_watchdog_arg = 0; @@ -141,7 +147,9 @@ ppc405_watchdog_setup(int tcr_wp, int tcr_wrc, mtspr(SPRN_TSR, TSR_WIS); isync(); - } else { + } + else + { // Install the new handler and enable the watchdog interrup. @@ -157,7 +165,7 @@ ppc405_watchdog_setup(int tcr_wp, int tcr_wrc, return SSX_OK; } - + /// Set up a PPC405 Debug interrupt handler /// @@ -167,7 +175,7 @@ ppc405_watchdog_setup(int tcr_wp, int tcr_wrc, /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_ARGUMENT_PPC405_DEBUG The \a handler argument +/// \retval -SSX_INVALID_ARGUMENT_PPC405_DEBUG The \a handler argument /// is null (0). // The debug handler is installed in an SSX_CRITICAL critical section with all diff --git a/src/ssx/ppc405/ppc405_lib_core.c b/src/ssx/ppc405/ppc405_lib_core.c index 334f08b..8f49e39 100644 --- a/src/ssx/ppc405/ppc405_lib_core.c +++ b/src/ssx/ppc405/ppc405_lib_core.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -29,11 +29,11 @@ //----------------------------------------------------------------------------- /// \file ppc405_lib_core.c -/// \brief PPC405-specific library procedures +/// \brief PPC405-specific library procedures /// /// The routines in this file are not part of SSX per se, but are included /// with SSX because they may be considered OS services. -/// +/// /// These are core routines that will present in all PPC405 SSX applications. #include "ssx.h" diff --git a/src/ssx/ppc405/ppc405_mmu.c b/src/ssx/ppc405/ppc405_mmu.c index 3509c36..9c44bd3 100644 --- a/src/ssx/ppc405/ppc405_mmu.c +++ b/src/ssx/ppc405/ppc405_mmu.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -89,7 +89,8 @@ uint64_t __ppc405_tlb_free = 0; int ppc405_mmu_reset() { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(mfmsr() & (MSR_IR | MSR_DR), PPC405_MMU_ILLEGAL_CONTEXT); } @@ -172,10 +173,10 @@ ppc405_mmu_reset() /// duplicated range is accessed. int -ppc405_mmu_map(SsxAddress effective_address, +ppc405_mmu_map(SsxAddress effective_address, SsxAddress real_address, size_t size, int tlbhi_flags, int tlblo_flags, - Ppc405MmuMap *map) + Ppc405MmuMap* map) { size_t log_page_size; size_t page_size = 0; @@ -186,7 +187,8 @@ ppc405_mmu_map(SsxAddress effective_address, uint64_t bit; SsxMachineContext ctx; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { uint64_t allocated; SsxAddress this_effective_address; int entry, overlap; @@ -213,7 +215,8 @@ ppc405_mmu_map(SsxAddress effective_address, // mappings that duplicate each other (a super-bug), but it should // protect against bugs in a single thread's updating of the TLB. - if (size != 0) { + if (size != 0) + { // See if the requested effective address is already mapped in the // TLB @@ -225,30 +228,35 @@ ppc405_mmu_map(SsxAddress effective_address, // range of the new request. allocated = ~__ppc405_tlb_free; - while (!overlap && (allocated != 0)) { + + while (!overlap && (allocated != 0)) + { entry = cntlz64(allocated); allocated &= ~((uint64_t)1 << (63 - entry)); tlbhi.value = tlbrehi(entry); - if (tlbhi.fields.v) { - this_effective_address = + if (tlbhi.fields.v) + { + + this_effective_address = tlbhi.fields.epn << PPC405_LOG_PAGE_SIZE_MIN; - + // See if the first byte of this entry is inside the // requested effective address range. NB: use actual // address ranges (addr + size - 1) to compute overlap to // avoid overflow. - overlap |= - (this_effective_address >= + overlap |= + (this_effective_address >= effective_address) && (this_effective_address <= (effective_address + size - 1)); } } + SSX_ERROR_IF(overlap, PPC405_DUPLICATE_TLB_ENTRY); } } @@ -258,12 +266,14 @@ ppc405_mmu_map(SsxAddress effective_address, // pages, by using the largest possible (aligned) page size for the // remaining memory area. - while (size != 0) { + while (size != 0) + { ssx_critical_section_enter(SSX_CRITICAL, &ctx); - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF_CRITICAL(__ppc405_tlb_free == 0, + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF_CRITICAL(__ppc405_tlb_free == 0, PPC405_TOO_MANY_TLB_ENTRIES, &ctx); } @@ -276,16 +286,23 @@ ppc405_mmu_map(SsxAddress effective_address, ssx_critical_section_exit(&ctx); log_page_size = PPC405_LOG_PAGE_SIZE_MAX; - do { + + do + { page_size = POW2_32(log_page_size); - if ((size >= page_size) && + + if ((size >= page_size) && ((effective_address & (page_size - 1)) == 0) && - ((real_address & (page_size - 1)) == 0)) { + ((real_address & (page_size - 1)) == 0)) + { break; - } else { + } + else + { log_page_size -= 2; } - } while (1); + } + while (1); size -= page_size; @@ -313,7 +330,8 @@ ppc405_mmu_map(SsxAddress effective_address, real_address += page_size; } - if (map) { + if (map) + { *map = local_map; } @@ -336,17 +354,19 @@ ppc405_mmu_map(SsxAddress effective_address, /// \retval -PPC405_MMU_INVALID_ARGUMENT The \a map pointer is null (0). int -ppc405_mmu_unmap(Ppc405MmuMap *map) +ppc405_mmu_unmap(Ppc405MmuMap* map) { int tlb_entry; uint64_t bit; SsxMachineContext ctx; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(map == 0, PPC405_MMU_INVALID_ARGUMENT); } - while ((tlb_entry = cntlz64(*map)) != 64) { + while ((tlb_entry = cntlz64(*map)) != 64) + { bit = 0x8000000000000000ull >> tlb_entry; *map &= ~bit; @@ -354,12 +374,12 @@ ppc405_mmu_unmap(Ppc405MmuMap *map) isync(); ssx_critical_section_enter(SSX_CRITICAL, &ctx); - + __ppc405_tlb_free |= bit; ssx_critical_section_exit(&ctx); } - + return 0; } @@ -379,39 +399,51 @@ ppc405_mmu_report(FILE* i_stream, Ppc405MmuMap* i_map) Ppc405Tlbhi tlbhi; Ppc405Tlblo tlblo; uint32_t size, eff_lo, eff_hi, real_lo, real_hi; - const char *size_string[] = { + const char* size_string[] = + { " 1K", " 4K", " 16K", " 64K", "256K", " 1M", " 4M", " 16M" }; Ppc405MmuMap map; fprintf(i_stream, "------------------------------------------------------------------------------\n"); - if (i_map == 0) { + + if (i_map == 0) + { fprintf(i_stream, "-- PPC405 MMU : Full Report --\n"); - } else { + } + else + { fprintf(i_stream, "-- PPC405 MMU : Partial Report --\n"); } + fprintf(i_stream, "------------------------------------------------------------------------------\n"); fprintf(i_stream, "-- # Effective Real Size EX/WR WIMG Other --\n"); fprintf(i_stream, "------------------------------------------------------------------------------\n"); - - if (i_map == 0) { - map = __ppc405_tlb_free; - } else { + + if (i_map == 0) + { + map = __ppc405_tlb_free; + } + else + { map = ~*i_map; } - for (i = 0; i < PPC405_TLB_ENTRIES; i++, map <<= 1) { + for (i = 0; i < PPC405_TLB_ENTRIES; i++, map <<= 1) + { - if (map & 0x8000000000000000ull) { + if (map & 0x8000000000000000ull) + { continue; } tlbhi.value = tlbrehi(i); tlblo.value = tlbrelo(i); - if (tlbhi.fields.v) { + if (tlbhi.fields.v) + { - size = + size = POW2_32(PPC405_LOG_PAGE_SIZE_MIN) << (2 * tlbhi.fields.size); eff_lo = tlbhi.fields.epn << PPC405_LOG_PAGE_SIZE_MIN; @@ -421,19 +453,21 @@ ppc405_mmu_report(FILE* i_stream, Ppc405MmuMap* i_map) real_hi = real_lo + size - 1; fprintf(i_stream, "-- %2d : %08x:%08x -> %08x:%08x : %s : %s %s : %s%s%s%s : %s%s --\n", - i, - eff_lo, eff_hi, - real_lo, real_hi, - size_string[tlbhi.fields.size], - tlblo.fields.ex ? "EX" : " ", - tlblo.fields.wr ? "WR" : " ", - tlblo.fields.w ? "W" : " ", - tlblo.fields.i ? "I" : " ", - tlblo.fields.m ? "M" : " ", - tlblo.fields.g ? "G" : " ", - tlbhi.fields.e ? "E" : " ", - tlbhi.fields.u0 ? "U0" : " "); - } else { + i, + eff_lo, eff_hi, + real_lo, real_hi, + size_string[tlbhi.fields.size], + tlblo.fields.ex ? "EX" : " ", + tlblo.fields.wr ? "WR" : " ", + tlblo.fields.w ? "W" : " ", + tlblo.fields.i ? "I" : " ", + tlblo.fields.m ? "M" : " ", + tlblo.fields.g ? "G" : " ", + tlbhi.fields.e ? "E" : " ", + tlbhi.fields.u0 ? "U0" : " "); + } + else + { fprintf(i_stream, "-- %2d : ENTRY NOT VALID\n", i); } } @@ -491,6 +525,6 @@ memcpy_real(void* dest, const void* src, size_t n) return dest; } - - + + diff --git a/src/ssx/ppc405/ppc405_mmu.h b/src/ssx/ppc405/ppc405_mmu.h index 058143c..64f8ac2 100644 --- a/src/ssx/ppc405/ppc405_mmu.h +++ b/src/ssx/ppc405/ppc405_mmu.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -45,9 +45,11 @@ /// field. When writing, TID is set from the current PID, and when reading PID /// is set from the TID entry of the register. -typedef union { +typedef union +{ uint32_t value; - struct { + struct + { uint32_t epn : 22; uint32_t size : 3; uint32_t v : 1; @@ -59,9 +61,11 @@ typedef union { /// The PPC405 TLBLO (Data) structure -typedef union { +typedef union +{ uint32_t value; - struct { + struct + { uint32_t rpn : 22; uint32_t ex : 1; uint32_t wr : 1; @@ -134,11 +138,11 @@ typedef uint64_t Ppc405MmuMap; /// TLBWEHI #define tlbwehi(entry, tlbhi) \ -asm volatile ("tlbwehi %0, %1" : : "r" (tlbhi), "r" (entry) : "memory") + asm volatile ("tlbwehi %0, %1" : : "r" (tlbhi), "r" (entry) : "memory") /// TLBWELO #define tlbwelo(entry, tlblo) \ -asm volatile ("tlbwelo %0, %1" : : "r" (tlblo), "r" (entry) : "memory") + asm volatile ("tlbwelo %0, %1" : : "r" (tlblo), "r" (entry) : "memory") /// TLBREHI #define tlbrehi(entry) \ @@ -172,17 +176,17 @@ int ppc405_mmu_reset(void); int -ppc405_mmu_map(SsxAddress effective_address, +ppc405_mmu_map(SsxAddress effective_address, SsxAddress real_address, size_t size, int tlbhi_flags, int tlblo_flags, - Ppc405MmuMap *map); + Ppc405MmuMap* map); int -ppc405_mmu_unmap(Ppc405MmuMap *map); +ppc405_mmu_unmap(Ppc405MmuMap* map); void ppc405_mmu_start(void); - + void ppc405_mmu_report(FILE* stream, Ppc405MmuMap* map); diff --git a/src/ssx/ppc405/ppc405_mmu_asm.S b/src/ssx/ppc405/ppc405_mmu_asm.S index d5fefd3..fc3e954 100644 --- a/src/ssx/ppc405/ppc405_mmu_asm.S +++ b/src/ssx/ppc405/ppc405_mmu_asm.S @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/ppc405/ppc405_msr.h b/src/ssx/ppc405/ppc405_msr.h index 213058f..b10d6cb 100644 --- a/src/ssx/ppc405/ppc405_msr.h +++ b/src/ssx/ppc405/ppc405_msr.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -64,9 +64,9 @@ /// Move From MSR #define mfmsr() \ - ({uint32_t __msr; \ - asm volatile ("mfmsr %0" : "=r" (__msr)); \ - __msr;}) + ({uint32_t __msr; \ + asm volatile ("mfmsr %0" : "=r" (__msr)); \ + __msr;}) /// Move to MSR @@ -86,7 +86,7 @@ /// operation is only guaranteed atomic in a critical section. #define andc_msr(x) \ - mtmsr(mfmsr() & ~(x)) + mtmsr(mfmsr() & ~(x)) /// Write MSR[EE] with an immediate value (0/1) diff --git a/src/ssx/ppc405/ppc405_spr.h b/src/ssx/ppc405/ppc405_spr.h index b73eb90..da28a69 100644 --- a/src/ssx/ppc405/ppc405_spr.h +++ b/src/ssx/ppc405/ppc405_spr.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -220,9 +220,11 @@ #ifndef __ASSEMBLER__ -typedef union { +typedef union +{ uint32_t value; - struct { + struct + { unsigned int wp : 2; unsigned int wrc : 2; unsigned int wie : 1; @@ -255,9 +257,9 @@ typedef union { /// Note that \a sprn must be a compile-time constant. #define mfspr(sprn) \ - ({uint32_t __value; \ - asm volatile ("mfspr %0, %1" : "=r" (__value) : "i" (sprn)); \ - __value;}) + ({uint32_t __value; \ + asm volatile ("mfspr %0, %1" : "=r" (__value) : "i" (sprn)); \ + __value;}) /// Move to SPR @@ -265,10 +267,10 @@ typedef union { /// Note that \a sprn must be a compile-time constant. #define mtspr(sprn, value) \ - ({uint32_t __value = (value); \ - asm volatile ("mtspr %0, %1" : : "i" (sprn), "r" (__value)); \ - }) - + ({uint32_t __value = (value); \ + asm volatile ("mtspr %0, %1" : : "i" (sprn), "r" (__value)); \ + }) + /// Read-Modify-Write an SPR with OR (Set SPR bits) /// @@ -307,6 +309,7 @@ typedef union { #endif /* __ASSEMBLER__ */ #ifdef __ASSEMBLER__ +// *INDENT-OFF* /// \cond @@ -336,6 +339,7 @@ typedef union { /// \endcond +// *INDENT-ON* #endif /* __ASSEMBLER__ */ #endif /* __PPC405_SPR_H__ */ diff --git a/src/ssx/ppc405/ppc405_thread_init.S b/src/ssx/ppc405/ppc405_thread_init.S index dca6184..89c0257 100644 --- a/src/ssx/ppc405/ppc405_thread_init.S +++ b/src/ssx/ppc405/ppc405_thread_init.S @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2014,2015 +# Contributors Listed Below - COPYRIGHT 2014,2016 # [+] International Business Machines Corp. # # @@ -29,6 +29,7 @@ /// The entry points in this file are routines that are typically used during /// initialization, and their code space could be deallocated and recovered if /// no longer needed by the application after initialization. +// *INDENT-OFF* .nolist #include "ssx.h" @@ -146,4 +147,5 @@ __ssx_thread_context_initialize: .epilogue __ssx_thread_context_initialize +// *INDENT-ON* /// \endcond diff --git a/src/ssx/ppc405/ssx_port_types.h b/src/ssx/ppc405/ssx_port_types.h index 4040b4a..cd46e08 100644 --- a/src/ssx/ppc405/ssx_port_types.h +++ b/src/ssx/ppc405/ssx_port_types.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -56,10 +56,10 @@ typedef uint8_t SsxIrqId; /// a thread queue). /// /// These queues are used both for the run queue and the pending queue -/// associated with every semaphore. +/// associated with every semaphore. /// /// On PPC405 with 32 threads (implied), this is a job for a uint32_t and -/// cntlzw(). +/// cntlzw(). typedef uint32_t SsxThreadQueue; diff --git a/src/ssx/ppc405/ssxppc405files.mk b/src/ssx/ppc405/ssxppc405files.mk index c91560e..4b8cdfa 100644 --- a/src/ssx/ppc405/ssxppc405files.mk +++ b/src/ssx/ppc405/ssxppc405files.mk @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2014,2015 +# Contributors Listed Below - COPYRIGHT 2014,2016 # [+] International Business Machines Corp. # # diff --git a/src/ssx/ssx/Makefile b/src/ssx/ssx/Makefile index e149e7f..f78e831 100644 --- a/src/ssx/ssx/Makefile +++ b/src/ssx/ssx/Makefile @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2014,2015 +# Contributors Listed Below - COPYRIGHT 2014,2016 # [+] International Business Machines Corp. # # diff --git a/src/ssx/ssx/ssx.h b/src/ssx/ssx/ssx.h index ff6c947..253530b 100644 --- a/src/ssx/ssx/ssx.h +++ b/src/ssx/ssx/ssx.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,23 +40,23 @@ /// assembly. #ifndef __ASSEMBLER__ -#include <stdint.h> -#include <stddef.h> + #include <stdint.h> + #include <stddef.h> #endif /* __ASSEMBLER__ */ #ifndef __SSX__ -#define __SSX__ 1 + #define __SSX__ 1 #endif /// The application environment specifies whether or not it will provide an /// application configuration file, which must be named "ssx_app_cfg.h". #ifndef USE_SSX_APP_CFG_H -#define USE_SSX_APP_CFG_H 0 + #define USE_SSX_APP_CFG_H 0 #endif #if USE_SSX_APP_CFG_H -#include "ssx_app_cfg.h" + #include "ssx_app_cfg.h" #endif #include "ssx_macros.h" @@ -94,7 +94,7 @@ __y++; \ } \ __y;}) - + #define POW2_32(x) ((uint32_t)1 << (x)) #define POW2_64(x) ((uint64_t)1 << (x)) @@ -119,7 +119,7 @@ /// initialized. Otherwise it confuses the linker which wants to put /// uninitialized data into .bss sections. /// -/// \code +/// \code /// /// int foo SECTION_ATTRIBUTE(".noncacheable") = 0; /// int bar[10] SECTION_ATTRIBUTE(".noncacheable") = {0}; @@ -132,14 +132,14 @@ /// This is required for example to avoid "function unused" warnings when a /// function is declared static but only referenced by inline assembler: /// -/// \code -/// +/// \code +/// /// static USED_ATTRIBUTE void -/// _checkstop(void* arg, SsxIrqId irq, int priority) +/// _checkstop(void* arg, SsxIrqId irq, int priority) /// { /// SSX_PANIC(VALIDATION_CHECKSTOP); /// } -/// +/// /// SSX_IRQ_FAST2FULL(_validationCheckstopHandler, _checkstop); /// /// \endcode diff --git a/src/ssx/ssx/ssx_api.h b/src/ssx/ssx/ssx_api.h index bcdd0fb..d3b63ff 100644 --- a/src/ssx/ssx/ssx_api.h +++ b/src/ssx/ssx/ssx_api.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -160,7 +160,7 @@ /// blocked on a semaphore with timeout). The flag SSX_THREAD_FLAG_TIMED_OUT /// indicates that a thread timer timed out before the thread became /// runnable. Currently only the semaphore-pend-with-timeout code uses this -/// flag. +/// flag. /// /// Note that a thread can be mapped and runnable (in the run queue) even /// though SSX_THREAD_FLAG_SEMAPHORE_PEND and/or SSX_THREAD_FLAG_TIMER_PEND @@ -180,7 +180,7 @@ // Critical Sections /// Enter a critical section of a given priority, saving the current machine -/// context. +/// context. #define ssx_critical_section_enter(priority, pctx) \ ssx_interrupt_disable(priority, pctx) @@ -205,22 +205,22 @@ // Application-overrideable definitions -/// Control whether or not the API functions check for errors. +/// Control whether or not the API functions check for errors. /// /// This definition can be overriden by the application. #ifndef SSX_ERROR_CHECK_API -#define SSX_ERROR_CHECK_API 1 + #define SSX_ERROR_CHECK_API 1 #endif /// Control whether API errors cause kernel panics or return negative error -/// codes. +/// codes. /// /// This selection is only valid if \c SSX_ERROR_CHECK_API is defined /// non-0. This definition can be overriden by the application. #ifndef SSX_ERROR_PANIC -#define SSX_ERROR_PANIC 1 + #define SSX_ERROR_PANIC 1 #endif /// Control whether or not the SSX kernel checks key invariants. @@ -229,7 +229,7 @@ /// definition can be overriden by the application. #ifndef SSX_ERROR_CHECK_KERNEL -#define SSX_ERROR_CHECK_KERNEL 1 + #define SSX_ERROR_CHECK_KERNEL 1 #endif /// Define the time interval type, which must be an unsigned type of a size @@ -237,22 +237,22 @@ /// overridden by the application. #ifndef SSX_TIME_INTERVAL_TYPE -#define SSX_TIME_INTERVAL_TYPE uint32_t + #define SSX_TIME_INTERVAL_TYPE uint32_t #endif /// Provide support for the SsxTimer APIs in addition to the default /// initerrupt APIs. This definition can be overridden by the application. #ifndef SSX_TIMER_SUPPORT -#define SSX_TIMER_SUPPORT 1 + #define SSX_TIMER_SUPPORT 1 #endif /// Provide support for the all SSX APIs. Thread support requires/implies /// support for time services and semaphores. This definition can be -/// overridden by the application. +/// overridden by the application. #ifndef SSX_THREAD_SUPPORT -#define SSX_THREAD_SUPPORT 1 + #define SSX_THREAD_SUPPORT 1 #endif /// Control the level of stack checking. @@ -260,7 +260,7 @@ /// This definition can be overriden by the application. /// /// 0 : No stack prepatterning or checking is made for thread and kernel -/// stacks. +/// stacks. /// /// 1 : Kernel interrupt stacks are prepatterned during /// \c ssx_initialize(). Thread stacks are prepatterned during @@ -271,9 +271,9 @@ /// noncritical interrupt processing. The maximum utilization is stored in /// the thread data structure. The kernel will panic if stack overflow is /// detected. Stack utilization is not computed for the idle thread. - + #ifndef SSX_STACK_CHECK -#define SSX_STACK_CHECK 1 + #define SSX_STACK_CHECK 1 #endif /// A hook for main() @@ -284,7 +284,7 @@ /// ssx_app_cfg.h. The SSX_MAIN_HOOK will run on the stack of main(). #ifndef SSX_MAIN_HOOK -#define SSX_MAIN_HOOK do {} while (0) + #define SSX_MAIN_HOOK do {} while (0) #endif /// A hook for ssx_start_threads() @@ -292,13 +292,13 @@ /// This hook macro is expanded in the call-tree of ssx_start_threads() before /// threads are actually started. The application can redefine this hook /// macro in (or in headers referred to in) the application header -/// ssx_app_cfg.h. +/// ssx_app_cfg.h. /// /// The SSX_START_THREADS_HOOK runs as a pseudo-interrupt handler on the /// noncritical interrupt stack, with noncritical interrupts disabled. #ifndef SSX_START_THREADS_HOOK -#define SSX_START_THREADS_HOOK do {} while (0) + #define SSX_START_THREADS_HOOK do {} while (0) #endif /// The maximum value of the \c SsxTimebase type. @@ -311,12 +311,12 @@ #define SSX_TIMEBASE_CONTINUES SSX_TIMEBASE_MAX /// By convention, a timeout value indicating 'no waiting' in a call of \c -/// ssx_semaphore_pend(). +/// ssx_semaphore_pend(). #define SSX_NO_WAIT 0 /// By convention, a timeout value indicating 'wait forever' in a call of \c -/// ssx_semaphore_pend(). +/// ssx_semaphore_pend(). #define SSX_WAIT_FOREVER ((SsxInterval)-1) @@ -334,7 +334,7 @@ /// ignored. The application can redefine this macro. #ifndef SSX_SECONDS -#define SSX_SECONDS(s) ((SsxInterval)(__ssx_timebase_frequency_hz * (SsxInterval)(s))) + #define SSX_SECONDS(s) ((SsxInterval)(__ssx_timebase_frequency_hz * (SsxInterval)(s))) #endif /// Convert a time in integral milliseconds to a time interval - overflows are @@ -342,7 +342,7 @@ /// assumed. The application can redefine this macro. #ifndef SSX_MILLISECONDS -#define SSX_MILLISECONDS(m) ((SsxInterval)(__ssx_timebase_frequency_khz * (SsxInterval)(m))) + #define SSX_MILLISECONDS(m) ((SsxInterval)(__ssx_timebase_frequency_khz * (SsxInterval)(m))) #endif /// Convert a time in integral microseconds to a time interval - overflows are @@ -350,7 +350,7 @@ /// assumed. The application can redefine this macro. #ifndef SSX_MICROSECONDS -#define SSX_MICROSECONDS(u) ((SsxInterval)(__ssx_timebase_frequency_mhz * (SsxInterval)(u))) + #define SSX_MICROSECONDS(u) ((SsxInterval)(__ssx_timebase_frequency_mhz * (SsxInterval)(u))) #endif /// Convert a time in integral nanoseconds to a time interval - overflows are @@ -365,38 +365,38 @@ /// Enable SSX application tracing (enabled by default) #ifndef SSX_TRACE_ENABLE -#define SSX_TRACE_ENABLE 1 + #define SSX_TRACE_ENABLE 1 #endif /// Enable SSX kernel tracing (disabled by default) #ifndef SSX_KERNEL_TRACE_ENABLE -#define SSX_KERNEL_TRACE_ENABLE 0 + #define SSX_KERNEL_TRACE_ENABLE 0 #endif #if !SSX_TRACE_ENABLE -#define SSX_TRACE(...) -#define SSX_TRACE_BIN(str, bufp, buf_size) + #define SSX_TRACE(...) + #define SSX_TRACE_BIN(str, bufp, buf_size) #else -#define SSX_TRACE(...) SSXTRACE(__VA_ARGS__) -#define SSX_TRACE_BIN(str, bufp, buf_size) SSXTRACE_BIN(str, bufp, buf_size) + #define SSX_TRACE(...) SSXTRACE(__VA_ARGS__) + #define SSX_TRACE_BIN(str, bufp, buf_size) SSXTRACE_BIN(str, bufp, buf_size) #endif //Kernel trace macros #if !SSX_KERNEL_TRACE_ENABLE -#define SSX_KERN_TRACE(...) -#define SSX_KERN_TRACE_ASM16(...) + #define SSX_KERN_TRACE(...) + #define SSX_KERN_TRACE_ASM16(...) #else -#define SSX_KERN_TRACE(...) SSX_TRACE(__VA_ARGS__) -#define SSX_KERN_TRACE_ASM16(...) SSX_TRACE_ASM16(__VA_ARGS__) + #define SSX_KERN_TRACE(...) SSX_TRACE(__VA_ARGS__) + #define SSX_KERN_TRACE_ASM16(...) SSX_TRACE_ASM16(__VA_ARGS__) #endif /* SSX_KERNEL_TRACE_ENABLE */ /// Add a string to the trace buffer with an optional register holding a 16bit value /// WARNING: This calls a c function which may clobber any of the volatile registers #if (SSX_TRACE_SUPPORT && SSX_TIMER_SUPPORT) -#define SSX_TRACE_ASM16(...) TRACE_ASM_HELPER16(VARG_COUNT(__VA_ARGS__), __VA_ARGS__) + #define SSX_TRACE_ASM16(...) TRACE_ASM_HELPER16(VARG_COUNT(__VA_ARGS__), __VA_ARGS__) #else -#define SSX_TRACE_ASM16(...) + #define SSX_TRACE_ASM16(...) #endif /* SSX_TRACE_SUPPORT */ /// The following macros are helper macros for tracing. They should not be called @@ -420,6 +420,7 @@ #define TINY_TRACE_ASM7() .error "too many parameters" //TODO: add support for tracing more than 1 parameter and binary data in assembly +// *INDENT-OFF* .global ssx_trace_tiny @@ -433,7 +434,8 @@ oris %r3, %r3, \hash16 bl ssx_trace_tiny .endm - + +// *INDENT-ON* #endif /*__ASSEMBLER__*/ @@ -469,7 +471,8 @@ typedef SSX_TIME_INTERVAL_TYPE SsxInterval; #include "ssx_port_types.h" -typedef struct { +typedef struct +{ /// A priority queue of threads pending on the semaphore. SsxThreadQueue pending_threads; @@ -490,8 +493,8 @@ typedef struct { /// arrays of semaphores. #define SSX_SEMAPHORE_INITIALIZATION(_initial_count, _max_count) \ {.pending_threads = 0, \ - .count = (_initial_count), \ - .max_count = (_max_count)} + .count = (_initial_count), \ + .max_count = (_max_count)} /// Declare and initialize a semaphore @@ -509,19 +512,19 @@ typedef struct { #define SSXTRACE2(str, parm0) \ ((sizeof(parm0) <= 2)? \ - ssx_trace_tiny(HASH_ARG_COMBO(str, parm0)): \ - ssx_trace_big(HASH_ARG_COMBO(str, 1), ((uint64_t)parm0) << 32, 0)) + ssx_trace_tiny(HASH_ARG_COMBO(str, parm0)): \ + ssx_trace_big(HASH_ARG_COMBO(str, 1), ((uint64_t)parm0) << 32, 0)) #define SSXTRACE3(str, parm0, parm1) \ - ssx_trace_big(HASH_ARG_COMBO(str, 2), ((((uint64_t)parm0) << 32) | parm1), 0) + ssx_trace_big(HASH_ARG_COMBO(str, 2), ((((uint64_t)parm0) << 32) | parm1), 0) #define SSXTRACE4(str, parm0, parm1, parm2) \ - ssx_trace_big(HASH_ARG_COMBO(str, 3), ((((uint64_t)parm0) << 32) | parm1),\ - ((uint64_t)parm2) << 32 ) - + ssx_trace_big(HASH_ARG_COMBO(str, 3), ((((uint64_t)parm0) << 32) | parm1),\ + ((uint64_t)parm2) << 32 ) + #define SSXTRACE5(str, parm0, parm1, parm2, parm3) \ - ssx_trace_big(HASH_ARG_COMBO(str, 4), ((((uint64_t)parm0) << 32) | parm1),\ - ((((uint64_t)parm2) << 32) | parm3) ) + ssx_trace_big(HASH_ARG_COMBO(str, 4), ((((uint64_t)parm0) << 32) | parm1),\ + ((((uint64_t)parm2) << 32) | parm3) ) #define SSXTRACE6(...) ssx_trace_tiny() //will fail at compile time #define SSXTRACE7(...) ssx_trace_tiny() //will fail at compile time @@ -532,7 +535,7 @@ typedef struct { #if (SSX_TRACE_SUPPORT && SSX_TIMER_SUPPORT) #define SSXTRACE(...) SSXTRACE_HELPER(VARG_COUNT(__VA_ARGS__), __VA_ARGS__) #define SSXTRACE_BIN(str, bufp, buf_size) \ - ssx_trace_binary(((buf_size < 255)? HASH_ARG_COMBO(str, buf_size): HASH_ARG_COMBO(str, 255)), bufp) + ssx_trace_binary(((buf_size < 255)? HASH_ARG_COMBO(str, buf_size): HASH_ARG_COMBO(str, 255)), bufp) #else #define SSXTRACE(...) #define SSXTRACE_BIN(str, bufp, buf_size) @@ -543,17 +546,17 @@ typedef struct { // as extern SsxTraceBuffer [and size_t] variables in the .c file as well // as include ssx_trace.h. #if (SSX_TRACE_ENABLE && SSX_TRACE_SUPPORT && SSX_TIMER_SUPPORT) -#define SSX_FLUSH_TRACE_BUF() dcache_flush(&g_ssx_trace_buf, g_ssx_trace_buf_size) + #define SSX_FLUSH_TRACE_BUF() dcache_flush(&g_ssx_trace_buf, g_ssx_trace_buf_size) #else -#define SSX_FLUSH_TRACE_BUF() + #define SSX_FLUSH_TRACE_BUF() #endif //Making sure we can still compile application codes if SSX tracing for some // reason isn't enabled. #if (SSX_TRACE_ENABLE && SSX_TRACE_SUPPORT && SSX_TIMER_SUPPORT) -#define SSX_TRACE_INIT(freqhz, time0) ssx_trace_init(freqhz, time0) + #define SSX_TRACE_INIT(freqhz, time0) ssx_trace_init(freqhz, time0) #else -#define SSX_TRACE_INIT(freqhz, time0) + #define SSX_TRACE_INIT(freqhz, time0) #endif /// A generic doubly-linked list object @@ -564,7 +567,8 @@ typedef struct { /// initial 'data member' of the structure. This allows a pointer to a queue /// element to be cast to a pointer to an SsxDeque and vice-versa. -typedef struct SsxDeque { +typedef struct SsxDeque +{ /// Pointer to the head or the next element in a deque. /// @@ -583,7 +587,7 @@ typedef struct SsxDeque { } SsxDeque; -typedef void (*SsxTimerCallback)(void *); +typedef void (*SsxTimerCallback)(void*); #define SSX_TIMER_CALLBACK(callback) void callback(void *) @@ -591,13 +595,14 @@ struct SsxTimer; /// The SSX timer object -typedef struct SsxTimer { +typedef struct SsxTimer +{ /// The time queue management pointers /// /// This pointer container is defined as the first element of the /// structure to allow the SsxTimer to be cast to an SsxDeque and - /// vice-versa. + /// vice-versa. SsxDeque deque; /// The absolute timeout of the timer. @@ -615,11 +620,11 @@ typedef struct SsxTimer { /// timeouts this field is initialized to __ssx_thread_timeout(). SsxTimerCallback callback; - /// Private data passed to the callback. + /// Private data passed to the callback. /// /// For SSX thread timers used to implement Sleep and semaphore pend this /// field is initialized to a pointer to the thread. - void *arg; + void* arg; /// Options for timer processing; See \ref ssx_timer_options uint8_t options; @@ -633,7 +638,7 @@ typedef struct SsxTimer { /// /// This is the normal mode for SsxTimer objects scheduled by SSX kernal /// mechanisms. The timer callbacks effectively run as if inside a -/// highest-priority thread, allowing other interrupts to preempt them. +/// highest-priority thread, allowing other interrupts to preempt them. #define SSX_TIMER_CALLBACK_PREEMPTIBLE 0x1 /// @} @@ -641,15 +646,16 @@ typedef struct SsxTimer { // Threads -typedef void (*SsxThreadRoutine)(void *arg); +typedef void (*SsxThreadRoutine)(void* arg); #define SSX_THREAD_ROUTINE(f) void f(void *arg); -typedef struct { +typedef struct +{ /// Stack pointer saved during context switches. Assembler code expects /// this to always be at address offset 0 from the thread pointer. - SsxAddress saved_stack_pointer; + SsxAddress saved_stack_pointer; /// This is 1 past the last valid byte address of the thread stack. /// Assembler code expects this to always be at address offset (sizeof @@ -662,8 +668,8 @@ typedef struct { SsxAddress stack_base; /// If the thread is blocked on a semaphore, then this is the semaphore the - /// thread is blocked on. - SsxSemaphore *semaphore; + /// thread is blocked on. + SsxSemaphore* semaphore; /// The thread priority. SsxThreadPriority priority; @@ -690,7 +696,7 @@ ssx_initialize(SsxAddress noncritical_stack, size_t critical_stack_size, SsxTimebase initial_timebase, uint32_t timebase_frequency_hz); - + // Timebase APIs @@ -722,40 +728,40 @@ ssx_interrupt_preemption_disable(void); // Timer APIs -int -ssx_timer_create(SsxTimer *timer, +int +ssx_timer_create(SsxTimer* timer, SsxTimerCallback callback, - void *arg); + void* arg); -int -ssx_timer_create_nonpreemptible(SsxTimer *timer, +int +ssx_timer_create_nonpreemptible(SsxTimer* timer, SsxTimerCallback callback, - void *arg); + void* arg); -int -ssx_timer_schedule_absolute(SsxTimer *timer, +int +ssx_timer_schedule_absolute(SsxTimer* timer, SsxTimebase time, SsxInterval period); -int -ssx_timer_schedule(SsxTimer *timer, +int +ssx_timer_schedule(SsxTimer* timer, SsxInterval interval, SsxInterval period); -int -ssx_timer_cancel(SsxTimer *timer); +int +ssx_timer_cancel(SsxTimer* timer); -int -ssx_timer_info_get(SsxTimer *timer, - SsxTimebase *timeout, - int *active); +int +ssx_timer_info_get(SsxTimer* timer, + SsxTimebase* timeout, + int* active); // Thread APIs int -ssx_thread_create(SsxThread *thread, +ssx_thread_create(SsxThread* thread, SsxThreadRoutine thread_routine, - void *arg, + void* arg, SsxAddress stack, size_t stack_size, SsxThreadPriority priority); @@ -764,13 +770,13 @@ int ssx_start_threads(void); int -ssx_thread_resume(SsxThread *thread); +ssx_thread_resume(SsxThread* thread); int -ssx_thread_suspend(SsxThread *thread); +ssx_thread_suspend(SsxThread* thread); int -ssx_thread_delete(SsxThread *thread); +ssx_thread_delete(SsxThread* thread); int ssx_complete(void); @@ -782,19 +788,19 @@ int ssx_sleep(SsxInterval interval); int -ssx_thread_info_get(SsxThread *thread, - SsxThreadState *state, - SsxThreadPriority *priority, - int *runnable); +ssx_thread_info_get(SsxThread* thread, + SsxThreadState* state, + SsxThreadPriority* priority, + int* runnable); -int -ssx_thread_priority_change(SsxThread *thread, +int +ssx_thread_priority_change(SsxThread* thread, SsxThreadPriority new_priority, - SsxThreadPriority *old_priority); + SsxThreadPriority* old_priority); int ssx_thread_at_priority(SsxThreadPriority priority, - SsxThread **thread); + SsxThread** thread); int ssx_thread_priority_swap(SsxThread* thread_a, SsxThread* thread_b); @@ -803,29 +809,29 @@ ssx_thread_priority_swap(SsxThread* thread_a, SsxThread* thread_b); // Semaphore APIs int -ssx_semaphore_create(SsxSemaphore *semaphore, +ssx_semaphore_create(SsxSemaphore* semaphore, SsxSemaphoreCount initial_count, SsxSemaphoreCount max_count); int -ssx_semaphore_post(SsxSemaphore *semaphore); +ssx_semaphore_post(SsxSemaphore* semaphore); int -ssx_semaphore_pend(SsxSemaphore *semaphore, +ssx_semaphore_pend(SsxSemaphore* semaphore, SsxInterval timeout); int -ssx_semaphore_release_all(SsxSemaphore *semaphore); +ssx_semaphore_release_all(SsxSemaphore* semaphore); int -ssx_semaphore_info_get(SsxSemaphore *semaphore, - SsxSemaphoreCount *count, - int *pending); +ssx_semaphore_info_get(SsxSemaphore* semaphore, + SsxSemaphoreCount* count, + int* pending); void -ssx_semaphore_post_handler(void *arg, - SsxIrqId irq, +ssx_semaphore_post_handler(void* arg, + SsxIrqId irq, int priority); // Misc. APIs @@ -835,26 +841,26 @@ ssx_halt() __attribute__ ((noreturn)); // Deque APIs -int -ssx_deque_sentinel_create(SsxDeque *deque); +int +ssx_deque_sentinel_create(SsxDeque* deque); #define SSX_DEQUE_SENTINEL_INIT(dq_addr) \ -{\ - .next = dq_addr, \ - .previous = dq_addr \ -} + {\ + .next = dq_addr, \ + .previous = dq_addr \ + } #define SSX_DEQUE_SENTINEL_STATIC_CREATE(deque) \ SsxDeque deque = SSX_DEQUE_SENTINEL_INIT(&deque) -int -ssx_deque_element_create(SsxDeque *element); +int +ssx_deque_element_create(SsxDeque* element); #define SSX_DEQUE_ELEMENT_INIT() \ -{\ - .next = 0, \ - .previous = 0 \ -} + {\ + .next = 0, \ + .previous = 0 \ + } #define SSX_DEQUE_ELEMENT_STATIC_CREATE(deque) \ SsxDeque deque = SSX_DEQUE_ELEMENT_INIT() @@ -868,8 +874,8 @@ ssx_deque_element_create(SsxDeque *element); /// /// \retval 1 The SsxDeque is empty -static inline int -ssx_deque_is_empty(SsxDeque *deque) +static inline int +ssx_deque_is_empty(SsxDeque* deque) { return (deque == deque->next); } @@ -883,8 +889,8 @@ ssx_deque_is_empty(SsxDeque *deque) /// /// \retval 1 The element is currently enqueued -static inline int -ssx_deque_is_queued(SsxDeque *element) +static inline int +ssx_deque_is_queued(SsxDeque* element) { return (element->next != 0); } @@ -899,8 +905,8 @@ ssx_deque_is_queued(SsxDeque *element) /// It is an error to call this API on an element that is already enqueued, /// but the API does not check for this error. -static inline void -ssx_deque_push_back(SsxDeque *deque, SsxDeque *element) +static inline void +ssx_deque_push_back(SsxDeque* deque, SsxDeque* element) { deque->previous->next = element; element->previous = deque->previous; @@ -918,15 +924,15 @@ ssx_deque_push_back(SsxDeque *deque, SsxDeque *element) /// It is an error to call this API on an element that is already enqueued, /// but the API does not check for this error. -static inline void -ssx_deque_push_front(SsxDeque *deque, SsxDeque *element) +static inline void +ssx_deque_push_front(SsxDeque* deque, SsxDeque* element) { deque->next->previous = element; element->next = deque->next; element->previous = deque; deque->next = element; } - + /// Pop an element from the head of a deque /// /// \param deque The sentinel node of a deque @@ -938,15 +944,18 @@ ssx_deque_push_front(SsxDeque *deque, SsxDeque *element) // The cast of 'head' is used to remove the 'volatile' attribute. -static inline SsxDeque * -ssx_deque_pop_front(SsxDeque *deque) +static inline SsxDeque* +ssx_deque_pop_front(SsxDeque* deque) { - SsxDeque *head; + SsxDeque* head; - if (ssx_deque_is_empty(deque)) { + if (ssx_deque_is_empty(deque)) + { return 0; - } else { - head = (SsxDeque *)(deque->next); + } + else + { + head = (SsxDeque*)(deque->next); deque->next = head->next; deque->next->previous = deque; head->next = 0; @@ -963,7 +972,7 @@ ssx_deque_pop_front(SsxDeque *deque) /// enqueued, but the API does not check for this error. static inline void -ssx_deque_delete(SsxDeque *element) +ssx_deque_delete(SsxDeque* element) { element->previous->next = element->next; element->next->previous = element->previous; @@ -985,7 +994,7 @@ void ssx_trace_init(uint32_t timebase_frequency_hz, /// Cast a pointer to another type, in a way that won't cause warnings #define SSX_CAST_POINTER(t, p) ((t)((SsxAddress)(p))) - + // Static Assert Macro for Compile time assertions. // - This macro can be used both inside and outside of a function. // - A value of false will cause the ASSERT to produce this error @@ -1012,7 +1021,7 @@ void ssx_trace_init(uint32_t timebase_frequency_hz, /// SSX follows the Unix convention that a successful call of an API returns 0 /// (SSX_OK), but returns a negative code in the event of failure, or to /// provide further information. The error codes are all defined as manifest -/// constants. +/// constants. /// /// Some negative codes returned by SSX APIs are not considered errors. These /// conditions are always checked, never cause a panic if they occur, and diff --git a/src/ssx/ssx/ssx_core.c b/src/ssx/ssx/ssx_core.c index 78fffbc..5fd364e 100644 --- a/src/ssx/ssx/ssx_core.c +++ b/src/ssx/ssx/ssx_core.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -66,9 +66,10 @@ __ssx_timer_handler() /// \retval -SSX_INVALID_DEQUE_SENTINEL The \a deque pointer was null int -ssx_deque_sentinel_create(SsxDeque *deque) +ssx_deque_sentinel_create(SsxDeque* deque) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(deque == 0, SSX_INVALID_DEQUE_SENTINEL); } @@ -83,16 +84,17 @@ ssx_deque_sentinel_create(SsxDeque *deque) /// /// SSX has no way of knowing whether the \a element is currently in use, so /// this API must only be called on unitialized or otherwise unused deque -/// elements. +/// elements. /// /// \retval 0 success /// /// \retval -SSX_INVALID_DEQUE_ELEMENT The \a element pointer was null int -ssx_deque_element_create(SsxDeque *element) +ssx_deque_element_create(SsxDeque* element) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(element == 0, SSX_INVALID_DEQUE_ELEMENT); } diff --git a/src/ssx/ssx/ssx_debug_ptrs.c b/src/ssx/ssx/ssx_debug_ptrs.c index 9247273..2d34bd8 100644 --- a/src/ssx/ssx/ssx_debug_ptrs.c +++ b/src/ssx/ssx/ssx_debug_ptrs.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -36,14 +36,14 @@ /// #include "ssx.h" -#include "ssx_trace.h" +#include "ssx_trace.h" #include "ssx_debug_ptrs.h" extern SsxTimebase ppc405_64bit_ext_timebase; #if SSX_TRACE_SUPPORT -extern SsxTraceBuffer g_ssx_trace_buf; + extern SsxTraceBuffer g_ssx_trace_buf; #endif ssx_debug_ptrs_t ssx_debug_ptrs SECTION_ATTRIBUTE(".debug_ptrs") = @@ -62,7 +62,7 @@ ssx_debug_ptrs_t ssx_debug_ptrs SECTION_ATTRIBUTE(".debug_ptrs") = #if SSX_THREAD_SUPPORT .debug_thread_table_ptr = &__ssx_priority_map, .debug_thread_table_size = sizeof(__ssx_priority_map), - .debug_thread_runq_ptr = (void*)&__ssx_run_queue, + .debug_thread_runq_ptr = (void*)& __ssx_run_queue, .debug_thread_runq_size = sizeof(__ssx_run_queue), #else .debug_thread_table_ptr = 0, diff --git a/src/ssx/ssx/ssx_debug_ptrs.h b/src/ssx/ssx/ssx_debug_ptrs.h index 0ff8097..ad658a7 100644 --- a/src/ssx/ssx/ssx_debug_ptrs.h +++ b/src/ssx/ssx/ssx_debug_ptrs.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/ssx/ssx_init.c b/src/ssx/ssx/ssx_init.c index e2212da..0aee583 100644 --- a/src/ssx/ssx/ssx_init.c +++ b/src/ssx/ssx/ssx_init.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,17 +42,17 @@ uint32_t __ssx_timebase_frequency_khz; uint32_t __ssx_timebase_frequency_mhz; -/// Initialize SSX. +/// Initialize SSX. /// /// \param noncritical_stack A stack area for noncritical interrupt handlers. /// /// \param noncritical_stack_size The size (in bytes) of the stack area for -/// noncritical interrupt handlers. +/// noncritical interrupt handlers. /// /// \param critical_stack A stack area for critical interrupt handlers. /// /// \param critical_stack_size The size (in bytes) of the stack area for -/// critical interrupt handlers. +/// critical interrupt handlers. /// /// \param initial_timebase The initial value of the SSX timebase. If this /// argument is given as the special value \c SSX_TIMEBASE_CONTINUE, then the @@ -67,7 +67,7 @@ uint32_t __ssx_timebase_frequency_mhz; /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_ARGUMENT_INIT A stack pointer is 0 or is given +/// \retval -SSX_INVALID_ARGUMENT_INIT A stack pointer is 0 or is given /// a 0 size. /// /// \retval -SSX_STACK_OVERFLOW One or both stacks are not large enough to @@ -88,7 +88,8 @@ ssx_initialize(SsxAddress noncritical_stack, { int rc; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((noncritical_stack == 0) || (noncritical_stack_size == 0) || (critical_stack == 0) || @@ -96,7 +97,8 @@ ssx_initialize(SsxAddress noncritical_stack, SSX_INVALID_ARGUMENT_INIT); } - if (initial_timebase != SSX_TIMEBASE_CONTINUES) { + if (initial_timebase != SSX_TIMEBASE_CONTINUES) + { __ssx_timebase_set(initial_timebase); } @@ -107,7 +109,9 @@ ssx_initialize(SsxAddress noncritical_stack, __ssx_thread_machine_context_default = SSX_THREAD_MACHINE_CONTEXT_DEFAULT; rc = __ssx_stack_init(&noncritical_stack, &noncritical_stack_size); - if (rc) { + + if (rc) + { return rc; } @@ -115,7 +119,9 @@ ssx_initialize(SsxAddress noncritical_stack, __ssx_noncritical_stack_size = noncritical_stack_size; rc = __ssx_stack_init(&critical_stack, &critical_stack_size); - if (rc) { + + if (rc) + { return rc; } @@ -134,25 +140,27 @@ ssx_initialize(SsxAddress noncritical_stack, #endif /* SSX_TIMER_SUPPORT */ #if SSX_THREAD_SUPPORT - + // Clear the priority map. The final entry [SSX_THREADS] is for the idle // thread. int i; - for (i = 0; i <= SSX_THREADS; i++) { + + for (i = 0; i <= SSX_THREADS; i++) + { __ssx_priority_map[i] = 0; } // Initialize the thread scheduler __ssx_thread_queue_clear(&__ssx_run_queue); - __ssx_current_thread = 0; + __ssx_current_thread = 0; __ssx_next_thread = 0; __ssx_delayed_switch = 0; #endif /* SSX_THREAD_SUPPORT */ - return SSX_OK; + return SSX_OK; } @@ -163,11 +171,11 @@ ssx_initialize(SsxAddress noncritical_stack, /// called. void -__ssx_main(int argc, char **argv) +__ssx_main(int argc, char** argv) { SSX_MAIN_HOOK; - int main(int argc, char **argv); + int main(int argc, char** argv); main(argc, argv); } @@ -176,6 +184,6 @@ __ssx_main(int argc, char **argv) - - - + + + diff --git a/src/ssx/ssx/ssx_kernel.h b/src/ssx/ssx/ssx_kernel.h index 940fd31..9e0aa81 100644 --- a/src/ssx/ssx/ssx_kernel.h +++ b/src/ssx/ssx/ssx_kernel.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,19 +40,19 @@ /// we should try it. #ifdef __SSX_CORE_C__ -#define IF__SSX_CORE_C__(x) x -#define UNLESS__SSX_CORE_C__(x) + #define IF__SSX_CORE_C__(x) x + #define UNLESS__SSX_CORE_C__(x) #else -#define IF__SSX_CORE_C__(x) -#define UNLESS__SSX_CORE_C__(x) x + #define IF__SSX_CORE_C__(x) + #define UNLESS__SSX_CORE_C__(x) x #endif #if SSX_MINIMIZE_KERNEL_CODE_SPACE -#define IF_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) x -#define UNLESS_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) + #define IF_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) x + #define UNLESS_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) #else -#define IF_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) -#define UNLESS_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) x + #define IF_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) + #define UNLESS_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) x #endif @@ -61,15 +61,15 @@ /// This is the stack pointer saved when switching from a thread or /// non-critical interrupt context to a full-mode critical interrupt context. -UNLESS__SSX_CORE_C__(extern) -volatile +UNLESS__SSX_CORE_C__(extern) +volatile SsxAddress __ssx_saved_sp_critical; /// The critical interrupt stack; constant once defined by the call of -/// ssx_initialize(). +/// ssx_initialize(). UNLESS__SSX_CORE_C__(extern) -volatile +volatile SsxAddress __ssx_critical_stack; /// This is the stack pointer saved when switching from a thread context to a @@ -80,7 +80,7 @@ volatile SsxAddress __ssx_saved_sp_noncritical; /// The non-critical interrupt stack; constant once defined by the call of -/// ssx_initialize(). +/// ssx_initialize(). UNLESS__SSX_CORE_C__(extern) volatile @@ -94,7 +94,7 @@ SsxThreadQueue __ssx_run_queue; /// This flag is set by \c __ssx_schedule() if a new highest-priority thread /// becomes runnable during an interrupt handler. The context switch will /// take place at the end of non-critical interrupt processing, and the -/// interrupt handling code will clear the flag. +/// interrupt handling code will clear the flag. UNLESS__SSX_CORE_C__(extern) volatile @@ -108,11 +108,11 @@ int __ssx_delayed_switch; /// - After ssx_initialize() but prior to ssx_start_threads() /// /// - After ssx_start_threads(), when no threads are runnable. In this case -/// the NULL (0) value indicates that the SSX idle thread is 'running'. +/// the NULL (0) value indicates that the SSX idle thread is 'running'. /// /// - After ssx_start_threads(), when the current (non-idle) thread has -/// completed or been deleted. -/// +/// completed or been deleted. +/// /// If \a __ssx_current_thread == 0 then there is no requirement to save any /// register state on a context switch, either because the SSX idle thread has /// no permanent context, or because any thread context on the kernel stack is @@ -136,15 +136,15 @@ SsxThread* __ssx_current_thread; /// SSX_NONCRITICAL interrupts. /// /// \a __ssx_next_thread may be NULL (0) under the following -/// conditions: +/// conditions: /// /// - After ssx_initialize() but prior to ssx_start_threads(), assuming no /// threads have been made runnable. /// /// - After ssx_start_threads(), when no threads are runnable. In this case /// the NULL (0) value indicates that the SSX idle thread is the next thread -/// to 'run'. -/// +/// to 'run'. +/// /// If \a __ssx_next_thread == 0 then there is no requirement to restore /// any register state on a context switch, because the SSX idle thread has /// no permanent context. @@ -196,7 +196,8 @@ SsxThread* __ssx_priority_map[SSX_THREADS + 1]; /// This structure is defined for use by the kernel, however applications /// could also use this structure to define their own time queues. -typedef struct { +typedef struct +{ /// A sentinel node for the time queue. /// @@ -236,15 +237,15 @@ SsxTimeQueue __ssx_time_queue; /// does not (must not) use this API. UNLESS__SSX_CORE_C__(extern) -inline SsxThread * +inline SsxThread* ssx_current(void) { - return (SsxThread *)__ssx_current_thread; + return (SsxThread*)__ssx_current_thread; } /// Set the timebase. This is only called at initialization. Machine -/// specific. +/// specific. void __ssx_timebase_set(SsxTimebase t); @@ -266,15 +267,15 @@ SSX_TIMER_CALLBACK(__ssx_thread_timeout); /// Generic stack initialization. Portable. int -__ssx_stack_init(SsxAddress *stack, - size_t *size); +__ssx_stack_init(SsxAddress* stack, + size_t* size); /// Machine-specific thread context initialization. -void -__ssx_thread_context_initialize(SsxThread *thread, - SsxThreadRoutine thread_routine, - void *arg); +void +__ssx_thread_context_initialize(SsxThread* thread, + SsxThreadRoutine thread_routine, + void* arg); /// Machine specific resumption of __ssx_next_thread at __ssx_next_priority /// without saving the current context. @@ -283,11 +284,11 @@ __ssx_next_thread_resume(void); /// Schedule a timer in the time queue. Portable. void -__ssx_timer_schedule(SsxTimer *timer); +__ssx_timer_schedule(SsxTimer* timer); /// Remove a timer from the time queue. Portable. int -__ssx_timer_cancel(SsxTimer *timer); +__ssx_timer_cancel(SsxTimer* timer); void __ssx_schedule(void); @@ -296,7 +297,7 @@ __ssx_schedule(void); // Call the application main(). Portable. void -__ssx_main(int argc, char **argv); +__ssx_main(int argc, char** argv); #endif /* __ASSEMBLER__ */ diff --git a/src/ssx/ssx/ssx_macros.h b/src/ssx/ssx/ssx_macros.h index b20ac83..780aa16 100644 --- a/src/ssx/ssx/ssx_macros.h +++ b/src/ssx/ssx/ssx_macros.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -73,7 +73,7 @@ /// This macro encapsulates error handling boilerplate in the SSX API /// functions, for errors that do not occur in critical sections. -/// The error handling will only be enabled when SSX_ERROR_CHECK_API +/// The error handling will only be enabled when SSX_ERROR_CHECK_API /// is enabled. #define SSX_ERROR_IF_CHECK_API(condition, code) \ diff --git a/src/ssx/ssx/ssx_semaphore_core.c b/src/ssx/ssx/ssx_semaphore_core.c index 300628e..21abcd4 100644 --- a/src/ssx/ssx/ssx_semaphore_core.c +++ b/src/ssx/ssx/ssx_semaphore_core.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -58,18 +58,19 @@ /// context. /// /// \retval -SSX_INVALID_SEMAPHORE_AT_POST The \a semaphore is a null (0) pointer. -/// +/// /// \retval -SSX_SEMAPHORE_OVERFLOW The \a max_count argument supplied when /// the semaphore was created is non-zero and the new internal count is /// greater than the \a max_count. int -ssx_semaphore_post(SsxSemaphore *semaphore) +ssx_semaphore_post(SsxSemaphore* semaphore) { SsxMachineContext ctx; SsxThreadPriority priority; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_POST); } @@ -78,7 +79,8 @@ ssx_semaphore_post(SsxSemaphore *semaphore) priority = __ssx_thread_queue_min(&(semaphore->pending_threads)); - if (priority != SSX_IDLE_THREAD_PRIORITY) { + if (priority != SSX_IDLE_THREAD_PRIORITY) + { __ssx_thread_queue_delete(&(semaphore->pending_threads), priority); __ssx_thread_queue_insert(&__ssx_run_queue, priority); @@ -87,19 +89,22 @@ ssx_semaphore_post(SsxSemaphore *semaphore) __ssx_schedule(); - } else { + } + else + { semaphore->count++; - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((semaphore->max_count > 0) && + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((semaphore->max_count > 0) && (semaphore->count > semaphore->max_count), SSX_SEMAPHORE_OVERFLOW); } } ssx_critical_section_exit(&ctx); - + return SSX_OK; } @@ -139,7 +144,7 @@ ssx_semaphore_post(SsxSemaphore *semaphore) /// constant as \c SSX_WAIT_FOREVER. /// /// Return values other than SSX_OK (0) are not necessarily errors; see \ref -/// ssx_errors +/// ssx_errors /// /// The following return codes are non-error codes: /// @@ -155,9 +160,9 @@ ssx_semaphore_post(SsxSemaphore *semaphore) /// \retval -SSX_ILLEGAL_CONTEXT The API was called from a critical interrupt /// context. /// -/// \retval -SSX_INVALID_SEMAPHORE_AT_PEND The \a semaphore is a null (0) +/// \retval -SSX_INVALID_SEMAPHORE_AT_PEND The \a semaphore is a null (0) /// pointer. -/// +/// /// \retval -SSX_SEMAPHORE_PEND_WOULD_BLOCK The call was made from an /// interrupt context (or before threads have been started), the semaphore /// internal count was 0 and a non-zero timeout was specified. @@ -165,39 +170,46 @@ ssx_semaphore_post(SsxSemaphore *semaphore) // Note: Casting __ssx_current_thread removes the 'volatile' attribute. int -ssx_semaphore_pend(SsxSemaphore *semaphore, +ssx_semaphore_pend(SsxSemaphore* semaphore, SsxInterval timeout) { SsxMachineContext ctx; SsxThreadPriority priority; - SsxThread *thread; - SsxTimer *timer = 0; + SsxThread* thread; + SsxTimer* timer = 0; int rc = SSX_OK; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_PEND); } ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); - if (semaphore->count != 0) { + if (semaphore->count != 0) + { semaphore->count--; - } else if (timeout == SSX_NO_WAIT) { + } + else if (timeout == SSX_NO_WAIT) + { rc = -SSX_SEMAPHORE_PEND_NO_WAIT; - } else { + } + else + { - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF_CRITICAL(!__ssx_kernel_context_thread(), + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF_CRITICAL(!__ssx_kernel_context_thread(), SSX_SEMAPHORE_PEND_WOULD_BLOCK, &ctx); } - thread = (SsxThread *)__ssx_current_thread; + thread = (SsxThread*)__ssx_current_thread; priority = thread->priority; __ssx_thread_queue_insert(&(semaphore->pending_threads), priority); @@ -207,7 +219,8 @@ ssx_semaphore_pend(SsxSemaphore *semaphore, SSX_KERN_TRACE("THREAD_SEMAPHORE_PEND(%d)", priority); - if (timeout != SSX_WAIT_FOREVER) { + if (timeout != SSX_WAIT_FOREVER) + { timer = &(thread->timer); timer->timeout = ssx_timebase_get() + timeout; __ssx_timer_schedule(timer); @@ -219,14 +232,19 @@ ssx_semaphore_pend(SsxSemaphore *semaphore, thread->flags &= ~SSX_THREAD_FLAG_SEMAPHORE_PEND; - if (thread->flags & SSX_THREAD_FLAG_TIMER_PEND) { - if (thread->flags & SSX_THREAD_FLAG_TIMED_OUT) { + if (thread->flags & SSX_THREAD_FLAG_TIMER_PEND) + { + if (thread->flags & SSX_THREAD_FLAG_TIMED_OUT) + { rc = -SSX_SEMAPHORE_PEND_TIMED_OUT; __ssx_thread_queue_delete(&(semaphore->pending_threads), thread->priority); - } else { + } + else + { __ssx_timer_cancel(timer); } - thread->flags &= + + thread->flags &= ~(SSX_THREAD_FLAG_TIMER_PEND | SSX_THREAD_FLAG_TIMED_OUT); } } @@ -258,7 +276,7 @@ ssx_semaphore_pend(SsxSemaphore *semaphore, /// \retval -SSX_ILLEGAL_CONTEXT The API was called from a critical interrupt /// context. /// -/// \retval -SSX_INVALID_SEMAPHORE_AT_RELEASE The \a semaphore is a null (0) +/// \retval -SSX_INVALID_SEMAPHORE_AT_RELEASE The \a semaphore is a null (0) /// pointer. int @@ -266,7 +284,8 @@ ssx_semaphore_release_all(SsxSemaphore* semaphore) { SsxMachineContext ctx; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_RELEASE); } @@ -281,8 +300,8 @@ ssx_semaphore_release_all(SsxSemaphore* semaphore) return SSX_OK; } - - + + /// Get information about a semaphore. /// /// \param semaphore A pointer to the SsxSemaphore to query @@ -304,23 +323,27 @@ ssx_semaphore_release_all(SsxSemaphore* semaphore) /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_SEMAPHORE_AT_INFO The \a semaphore is a null (0) +/// \retval -SSX_INVALID_SEMAPHORE_AT_INFO The \a semaphore is a null (0) /// pointer. int ssx_semaphore_info_get(SsxSemaphore* semaphore, SsxSemaphoreCount* count, int* pending) - + { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_INFO); } - if (count) { + if (count) + { *count = semaphore->count; } - if (pending) { + + if (pending) + { *pending = __ssx_thread_queue_count(&(semaphore->pending_threads)); } @@ -336,7 +359,7 @@ ssx_semaphore_info_get(SsxSemaphore* semaphore, /// ssx_irq_handler_set(). The semaphore should be initialized with /// ssx_semaphore_create(&sem, 0, 1). This handler simply disables (masks) /// the interrupt, clears the status and calls ssx_semaphore_post() on the -/// semaphore. +/// semaphore. /// /// Note that clearing the status in the interrupt controller as done here is /// effectively a no-op for level-sensitive interrupts. In the level-sensitive @@ -344,11 +367,11 @@ ssx_semaphore_info_get(SsxSemaphore* semaphore, /// condition in the device before re-enabling the interrupt. void -ssx_semaphore_post_handler_full(void *arg, SsxIrqId irq, int priority) +ssx_semaphore_post_handler_full(void* arg, SsxIrqId irq, int priority) { ssx_irq_disable(irq); ssx_irq_status_clear(irq); - ssx_semaphore_post((SsxSemaphore *)arg); + ssx_semaphore_post((SsxSemaphore*)arg); } SSX_IRQ_FAST2FULL(ssx_semaphore_post_handler, ssx_semaphore_post_handler_full); diff --git a/src/ssx/ssx/ssx_semaphore_init.c b/src/ssx/ssx/ssx_semaphore_init.c index 9d0c099..0d5a432 100644 --- a/src/ssx/ssx/ssx_semaphore_init.c +++ b/src/ssx/ssx/ssx_semaphore_init.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -44,7 +44,7 @@ /// \param initial_count The initial count of the semaphore /// /// \param max_count The maximum count allowed in the semaphore, for error -/// checking +/// checking /// /// Semaphores are created (initialized) by a call of \c /// ssx_semaphore_create(), using an application-provided instance of an \c @@ -76,18 +76,19 @@ /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_SEMAPHORE_AT_CREATE The \a semaphore is a null (0) +/// \retval -SSX_INVALID_SEMAPHORE_AT_CREATE The \a semaphore is a null (0) /// pointer. -/// -/// \retval -SSX_INVALID_ARGUMENT_SEMAPHORE The \a max_count is non-zero +/// +/// \retval -SSX_INVALID_ARGUMENT_SEMAPHORE The \a max_count is non-zero /// and less than the \a initial_count. int -ssx_semaphore_create(SsxSemaphore *semaphore, +ssx_semaphore_create(SsxSemaphore* semaphore, SsxSemaphoreCount initial_count, SsxSemaphoreCount max_count) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_CREATE); SSX_ERROR_IF((max_count != 0) && (initial_count > max_count), SSX_INVALID_ARGUMENT_SEMAPHORE); @@ -100,7 +101,7 @@ ssx_semaphore_create(SsxSemaphore *semaphore, return SSX_OK; } - + diff --git a/src/ssx/ssx/ssx_stack_init.c b/src/ssx/ssx/ssx_stack_init.c index ef81fb1..a7892e6 100644 --- a/src/ssx/ssx/ssx_stack_init.c +++ b/src/ssx/ssx/ssx_stack_init.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -41,8 +41,8 @@ #include "ssx.h" -/// Initialize a stack area. -/// +/// Initialize a stack area. +/// /// \param stack A pointer to the smallest legal address of the stack. The /// stack address is modified as the stack is aligned and initialized. /// @@ -53,17 +53,18 @@ /// SSX makes no assumptions about size or alignment of the area provided as a /// stack, and carefully aligns and initializes the stack. Regardless of how /// the stack grows, the \a stack parameter is considered to be the lowest -/// legal address of the stack. +/// legal address of the stack. int -__ssx_stack_init(SsxAddress *stack, - size_t *size) +__ssx_stack_init(SsxAddress* stack, + size_t* size) { SsxAddress mask; size_t excess, i, count; - SSX_STACK_TYPE *p; + SSX_STACK_TYPE* p; - if (SSX_STACK_DIRECTION < 0) { + if (SSX_STACK_DIRECTION < 0) + { // Stacks grow down. The initial stack pointer is set to just above // the last allocated stack address. This is legal for pre-decrement @@ -74,7 +75,8 @@ __ssx_stack_init(SsxAddress *stack, *stack += *size; - if (!SSX_STACK_PRE_DECREMENT) { + if (!SSX_STACK_PRE_DECREMENT) + { *stack -= sizeof(SSX_STACK_TYPE); *size -= sizeof(SSX_STACK_TYPE); } @@ -85,13 +87,19 @@ __ssx_stack_init(SsxAddress *stack, *size -= excess; *size = (*size / sizeof(SSX_STACK_TYPE)) * sizeof(SSX_STACK_TYPE); - if (SSX_STACK_CHECK) { - p = (SSX_STACK_TYPE *)(*stack); + if (SSX_STACK_CHECK) + { + p = (SSX_STACK_TYPE*)(*stack); count = *size / sizeof(SSX_STACK_TYPE); - for (i = 0; i < count; i++) { - if (SSX_STACK_PRE_DECREMENT) { + + for (i = 0; i < count; i++) + { + if (SSX_STACK_PRE_DECREMENT) + { *(--p) = SSX_STACK_PATTERN; - } else { + } + else + { *(p--) = SSX_STACK_PATTERN; } } @@ -99,7 +107,9 @@ __ssx_stack_init(SsxAddress *stack, __ssx_stack_create_initial_frame(stack, size); - } else { + } + else + { SSX_PANIC(SSX_UNIMPLEMENTED); } diff --git a/src/ssx/ssx/ssx_thread_core.c b/src/ssx/ssx/ssx_thread_core.c index f6d8a62..3408a9e 100644 --- a/src/ssx/ssx/ssx_thread_core.c +++ b/src/ssx/ssx/ssx_thread_core.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -43,7 +43,7 @@ // at entry. static inline int -__ssx_thread_is_active(SsxThread *thread) +__ssx_thread_is_active(SsxThread* thread) { return ((thread->state != SSX_THREAD_STATE_COMPLETED) && (thread->state != SSX_THREAD_STATE_DELETED)); @@ -51,10 +51,10 @@ __ssx_thread_is_active(SsxThread *thread) // This routine is only used locally. Noncritical interrupts must be disabled -// at entry. +// at entry. static inline int -__ssx_thread_is_mapped(SsxThread *thread) +__ssx_thread_is_mapped(SsxThread* thread) { return (thread->state == SSX_THREAD_STATE_MAPPED); } @@ -64,7 +64,7 @@ __ssx_thread_is_mapped(SsxThread *thread) // at entry. This is only called on mapped threads. static inline int -__ssx_thread_is_runnable(SsxThread *thread) +__ssx_thread_is_runnable(SsxThread* thread) { return __ssx_thread_queue_member(&__ssx_run_queue, thread->priority); } @@ -98,18 +98,24 @@ __ssx_thread_map(SsxThread* thread) priority = thread->priority; __ssx_priority_map[priority] = thread; - if (thread->state == SSX_THREAD_STATE_SUSPENDED_RUNNABLE) { + if (thread->state == SSX_THREAD_STATE_SUSPENDED_RUNNABLE) + { __ssx_thread_queue_insert(&__ssx_run_queue, priority); - } else if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) { + } + else if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) + { - if (thread->semaphore->count) { + if (thread->semaphore->count) + { thread->semaphore->count--; __ssx_thread_queue_insert(&__ssx_run_queue, priority); - } else { + } + else + { __ssx_thread_queue_insert(&(thread->semaphore->pending_threads), priority); @@ -118,18 +124,24 @@ __ssx_thread_map(SsxThread* thread) thread->state = SSX_THREAD_STATE_MAPPED; - if (SSX_KERNEL_TRACE_ENABLE) { - if (__ssx_thread_is_runnable(thread)) { + if (SSX_KERNEL_TRACE_ENABLE) + { + if (__ssx_thread_is_runnable(thread)) + { SSX_KERN_TRACE("THREAD_MAPPED_RUNNABLE(%d)", priority); - } else if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) { + } + else if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) + { SSX_KERN_TRACE("THREAD_MAPPED_SEMAPHORE_PEND(%d)", priority); - } else { + } + else + { SSX_KERN_TRACE("THREAD_MAPPED_SLEEPING(%d)", priority); } } -} +} + - // This routine is only used locally. Noncritical interrupts must be disabled // at entry. This routine is only ever called on threads in the // SSX_THREAD_STATE_MAPPED. Unmapping a thread removes it from the priority @@ -138,23 +150,28 @@ __ssx_thread_map(SsxThread* thread) // __ssx_thread_unmap(). void -__ssx_thread_unmap(SsxThread *thread) +__ssx_thread_unmap(SsxThread* thread) { SsxThreadPriority priority; priority = thread->priority; __ssx_priority_map[priority] = 0; - if (__ssx_thread_is_runnable(thread)) { + if (__ssx_thread_is_runnable(thread)) + { thread->state = SSX_THREAD_STATE_SUSPENDED_RUNNABLE; __ssx_thread_queue_delete(&__ssx_run_queue, priority); - } else { + } + else + { thread->state = SSX_THREAD_STATE_SUSPENDED_BLOCKED; - if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) { - __ssx_thread_queue_delete(&(thread->semaphore->pending_threads), + + if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) + { + __ssx_thread_queue_delete(&(thread->semaphore->pending_threads), priority); } } @@ -182,16 +199,24 @@ __ssx_schedule(void) __ssx_next_thread = __ssx_priority_map[__ssx_next_priority]; if ((__ssx_next_thread == 0) || - (__ssx_next_thread != __ssx_current_thread)) { - - if (__ssx_kernel_mode_thread()) { - if (__ssx_kernel_context_thread()) { - if (__ssx_current_thread != 0) { + (__ssx_next_thread != __ssx_current_thread)) + { + + if (__ssx_kernel_mode_thread()) + { + if (__ssx_kernel_context_thread()) + { + if (__ssx_current_thread != 0) + { __ssx_switch(); - } else { + } + else + { __ssx_next_thread_resume(); } - } else { + } + else + { __ssx_delayed_switch = 1; } } @@ -199,7 +224,7 @@ __ssx_schedule(void) } -// This routine is only used locally. +// This routine is only used locally. // // Completion and deletion are pretty much the same thing. Completion is // simply self-deletion of the current thread (which is mapped by @@ -218,7 +243,7 @@ __ssx_schedule(void) // tag only encodes the priority, which may be in use by a mapped thread. void -__ssx_thread_delete(SsxThread *thread, SsxThreadState final_state) +__ssx_thread_delete(SsxThread* thread, SsxThreadState final_state) { SsxMachineContext ctx; int mapped; @@ -227,26 +252,34 @@ __ssx_thread_delete(SsxThread *thread, SsxThreadState final_state) mapped = __ssx_thread_is_mapped(thread); - if (mapped) { + if (mapped) + { __ssx_thread_unmap(thread); } __ssx_timer_cancel(&(thread->timer)); thread->state = final_state; - if (mapped) { + if (mapped) + { - if (SSX_KERNEL_TRACE_ENABLE) { - if (final_state == SSX_THREAD_STATE_DELETED) { + if (SSX_KERNEL_TRACE_ENABLE) + { + if (final_state == SSX_THREAD_STATE_DELETED) + { SSX_KERN_TRACE("THREAD_DELETED(%d)", thread->priority); - } else { + } + else + { SSX_KERN_TRACE("THREAD_COMPLETED(%d)", thread->priority); } - } - - if (thread == __ssx_current_thread) { + } + + if (thread == __ssx_current_thread) + { __ssx_current_thread = 0; } + __ssx_schedule(); } @@ -274,33 +307,36 @@ __ssx_thread_delete(SsxThread *thread, SsxThreadState final_state) // tag only encodes the priority, which may be in use by a mapped thread. void -__ssx_thread_timeout(void *arg) +__ssx_thread_timeout(void* arg) { - SsxThread *thread = (SsxThread *)arg; + SsxThread* thread = (SsxThread*)arg; - switch (thread->state) { + switch (thread->state) + { - case SSX_THREAD_STATE_MAPPED: - if (!__ssx_thread_is_runnable(thread)) { - thread->flags |= SSX_THREAD_FLAG_TIMED_OUT; - __ssx_thread_queue_insert(&__ssx_run_queue, thread->priority); - __ssx_schedule(); - } - break; + case SSX_THREAD_STATE_MAPPED: + if (!__ssx_thread_is_runnable(thread)) + { + thread->flags |= SSX_THREAD_FLAG_TIMED_OUT; + __ssx_thread_queue_insert(&__ssx_run_queue, thread->priority); + __ssx_schedule(); + } - case SSX_THREAD_STATE_SUSPENDED_RUNNABLE: - break; + break; - case SSX_THREAD_STATE_SUSPENDED_BLOCKED: - thread->flags |= SSX_THREAD_FLAG_TIMED_OUT; - thread->state = SSX_THREAD_STATE_SUSPENDED_RUNNABLE; - break; + case SSX_THREAD_STATE_SUSPENDED_RUNNABLE: + break; - default: - SSX_PANIC(SSX_THREAD_TIMEOUT_STATE); + case SSX_THREAD_STATE_SUSPENDED_BLOCKED: + thread->flags |= SSX_THREAD_FLAG_TIMED_OUT; + thread->state = SSX_THREAD_STATE_SUSPENDED_RUNNABLE; + break; + + default: + SSX_PANIC(SSX_THREAD_TIMEOUT_STATE); } } - + // This routine serves as a container for the SSX_START_THREADS_HOOK and // actually starts threads. The helper routine __ssx_call_ssx_start_threads() @@ -328,7 +364,7 @@ __ssx_start_threads(void) SSX_PANIC(SSX_START_THREADS_RETURNED); } - + /// Start SSX threads /// @@ -349,7 +385,8 @@ __ssx_start_threads(void) int ssx_start_threads(void) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(__ssx_kernel_mode_thread(), SSX_ILLEGAL_CONTEXT_THREAD); } @@ -370,12 +407,12 @@ ssx_start_threads(void) /// is currently mapped at the priority assigned to the thread. SSX provides /// the ssx_thread_at_priority() API which allows an application-level /// scheduler to correctly manage multiple threads running at the same -/// priority. +/// priority. /// /// If the thread was sleeping while suspended it remains asleep. However if /// the sleep timer timed out while the thread was suspended it will be /// resumed runnable. -/// +/// /// If the thread was blocked on a semaphore when it was suspended, then when /// the thread is resumed it will attempt to reacquire the semaphore. /// However, if the thread was blocked on a semaphore with timeout while @@ -385,48 +422,53 @@ ssx_start_threads(void) /// It is not an error to call ssx_thread_resume() on a mapped /// thread. However it is an error to call ssx_thread_resume() on a completed /// or deleted thread. -/// +/// /// Return values other than SSX_OK (0) are errors; see \ref ssx_errors /// /// \retval 0 Successful completion, including calls on a \a thread that is /// already mapped. /// -/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called -/// from a critical interrupt context. +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called +/// from a critical interrupt context. /// /// \retval -SSX_INVALID_THREAD_AT_RESUME1 The \a thread is a null (0) pointer. -/// -/// \retval -SSX_INVALID_THREAD_AT_RESUME2 The \a thread is not active, +/// +/// \retval -SSX_INVALID_THREAD_AT_RESUME2 The \a thread is not active, /// i.e. has completed or been deleted. -/// -/// \retval -SSX_PRIORITY_IN_USE_AT_RESUME Another thread is already mapped at +/// +/// \retval -SSX_PRIORITY_IN_USE_AT_RESUME Another thread is already mapped at /// the priority of the \a thread. int -ssx_thread_resume(SsxThread *thread) +ssx_thread_resume(SsxThread* thread) { SsxMachineContext ctx; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_RESUME1); } ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL(!__ssx_thread_is_active(thread), SSX_INVALID_THREAD_AT_RESUME2, &ctx); } - if (!__ssx_thread_is_mapped(thread)) { + if (!__ssx_thread_is_mapped(thread)) + { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL(__ssx_priority_map[thread->priority] != 0, SSX_PRIORITY_IN_USE_AT_RESUME, &ctx); } + __ssx_thread_map(thread); __ssx_schedule(); } @@ -447,7 +489,7 @@ ssx_thread_resume(SsxThread *thread) /// /// If a sleeping thread is suspended, the sleep timer remains active but a /// timeout of the timer simply marks the thread as runnable, but does not -/// resume the thread. +/// resume the thread. /// /// If a thread blocked on a semaphore is suspended, the thread no longer /// participates in the semaphore mutual exclusion. If the thread is later @@ -465,33 +507,36 @@ ssx_thread_resume(SsxThread *thread) /// \retval 0 Successful completion, including calls on a \a thread that is /// already suspended. /// -/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called from a critical -/// interrupt context. +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called from a critical +/// interrupt context. /// /// \retval -SSX_INVALID_THREAD_AT_SUSPEND1 The \a thread is a null (0) pointer -/// -/// \retval -SSX_INVALID_THREAD_AT_SUSPEND2 The \a thread is not active, +/// +/// \retval -SSX_INVALID_THREAD_AT_SUSPEND2 The \a thread is not active, /// i.e. has completed or been deleted. int -ssx_thread_suspend(SsxThread *thread) +ssx_thread_suspend(SsxThread* thread) { SsxMachineContext ctx; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); SSX_ERROR_IF((thread == 0), SSX_INVALID_THREAD_AT_SUSPEND1); } ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL(!__ssx_thread_is_active(thread), SSX_INVALID_THREAD_AT_SUSPEND2, &ctx); } - if (__ssx_thread_is_mapped(thread)) { + if (__ssx_thread_is_mapped(thread)) + { SSX_KERN_TRACE("THREAD_SUSPENDED(%d)", thread->priority); __ssx_thread_unmap(thread); @@ -502,7 +547,7 @@ ssx_thread_suspend(SsxThread *thread) return SSX_OK; } - + /// Delete a thread /// @@ -521,17 +566,18 @@ ssx_thread_suspend(SsxThread *thread) /// thread deletes itself this API does not return at all. /// /// \retval 0 Successful completion, including calls on a \a thread that has -/// completed or had already been deleted. +/// completed or had already been deleted. /// -/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called from a critical -/// interrupt context. +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called from a critical +/// interrupt context. /// /// \retval -SSX_INVALID_THREAD_AT_DELETE The \a thread is a null (0) pointer. int -ssx_thread_delete(SsxThread *thread) +ssx_thread_delete(SsxThread* thread) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_DELETE); } @@ -561,7 +607,7 @@ ssx_thread_delete(SsxThread *thread) /// a successful completion this API does not return to the caller, which is /// always the thread context being completed. /// -/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread /// context. // Note: Casting __ssx_current_thread removes the 'volatile' attribute. @@ -569,11 +615,12 @@ ssx_thread_delete(SsxThread *thread) int ssx_complete(void) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_UNLESS_THREAD_CONTEXT(); } - __ssx_thread_delete((SsxThread *)__ssx_current_thread, + __ssx_thread_delete((SsxThread*)__ssx_current_thread, SSX_THREAD_STATE_COMPLETED); return SSX_OK; @@ -604,7 +651,7 @@ ssx_complete(void) /// /// \retval 0 Successful completion. /// -/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread /// context. // Note: Casting __ssx_current_thread removes the 'volatile' attribute. @@ -613,15 +660,16 @@ int ssx_sleep_absolute(SsxTimebase time) { SsxMachineContext ctx; - SsxThread *current; + SsxThread* current; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_UNLESS_THREAD_CONTEXT(); } ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); - current = (SsxThread *)__ssx_current_thread; + current = (SsxThread*)__ssx_current_thread; current->timer.timeout = time; __ssx_timer_schedule(&(current->timer)); @@ -667,11 +715,11 @@ ssx_sleep_absolute(SsxTimebase time) /// /// \retval 0 Successful completion. /// -/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread /// context. int -ssx_sleep(SsxInterval interval) +ssx_sleep(SsxInterval interval) { return ssx_sleep_absolute(ssx_timebase_get() + interval); } @@ -707,26 +755,33 @@ ssx_sleep(SsxInterval interval) /// \retval -SSX_INVALID_THREAD_AT_INFO The \a thread is a null (0) pointer. int -ssx_thread_info_get(SsxThread *thread, - SsxThreadState *state, - SsxThreadPriority *priority, - int *runnable) +ssx_thread_info_get(SsxThread* thread, + SsxThreadState* state, + SsxThreadPriority* priority, + int* runnable) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_INFO); } - if (state) { + if (state) + { *state = thread->state; } - if (priority) { + + if (priority) + { *priority = thread->priority; } - if (runnable) { + + if (runnable) + { *runnable = ((thread->state == SSX_THREAD_STATE_MAPPED) && __ssx_thread_queue_member(&__ssx_run_queue, thread->priority)); } + return SSX_OK; } @@ -755,10 +810,10 @@ ssx_thread_info_get(SsxThread *thread, /// \retval 0 Successful completion, including the redundant case of /// attempting to change the priority of the thread to its current priority. /// -/// \retval -SSX_ILLEGAL_CONTEXT_THREAD the API was called from a critical -/// interrupt context. +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD the API was called from a critical +/// interrupt context. /// -/// \retval -SSX_INVALID_THREAD_AT_CHANGE The \a thread is null (0) or +/// \retval -SSX_INVALID_THREAD_AT_CHANGE The \a thread is null (0) or /// otherwise invalid. /// /// \retval -SSX_INVALID_ARGUMENT_THREAD_CHANGE The \a new_priority is invalid. @@ -766,34 +821,40 @@ ssx_thread_info_get(SsxThread *thread, /// \retval -SSX_PRIORITY_IN_USE_AT_CHANGE The \a thread is mapped and the \a /// new_priority is currently in use by another thread. -int -ssx_thread_priority_change(SsxThread *thread, +int +ssx_thread_priority_change(SsxThread* thread, SsxThreadPriority new_priority, - SsxThreadPriority *old_priority) + SsxThreadPriority* old_priority) { SsxMachineContext ctx; SsxThreadPriority priority; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_CHANGE); - SSX_ERROR_IF(new_priority > SSX_THREADS, - SSX_INVALID_ARGUMENT_THREAD_CHANGE); + SSX_ERROR_IF(new_priority > SSX_THREADS, + SSX_INVALID_ARGUMENT_THREAD_CHANGE); } ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); priority = thread->priority; - if (priority != new_priority) { + if (priority != new_priority) + { - if (!__ssx_thread_is_mapped(thread)) { + if (!__ssx_thread_is_mapped(thread)) + { thread->priority = new_priority; - } else { + } + else + { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL(__ssx_priority_map[new_priority] != 0, SSX_PRIORITY_IN_USE_AT_CHANGE, &ctx); @@ -806,7 +867,8 @@ ssx_thread_priority_change(SsxThread *thread, } } - if (old_priority) { + if (old_priority) + { *old_priority = priority; } @@ -834,14 +896,15 @@ ssx_thread_priority_change(SsxThread *thread, /// /// \retval 0 Successful completion. /// -/// \retval -SSX_INVALID_ARGUMENT_THREAD_PRIORITY The \a priority is invalid -/// or the \a thread parameter is null (0). +/// \retval -SSX_INVALID_ARGUMENT_THREAD_PRIORITY The \a priority is invalid +/// or the \a thread parameter is null (0). int ssx_thread_at_priority(SsxThreadPriority priority, - SsxThread **thread) + SsxThread** thread) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((priority > SSX_THREADS) || (thread == 0), SSX_INVALID_ARGUMENT_THREAD_PRIORITY); } @@ -876,7 +939,7 @@ ssx_thread_at_priority(SsxThreadPriority priority, /// mapped after the call of ssx_thread_priority_swap() if and only if it was /// mapped prior to the call. If the new priority of a mapped thread is /// currently in use (by a thread other than the swap partner), then the -/// SSX_PRIORITY_IN_USE_AT_SWAP error is signalled and the swap does not take +/// SSX_PRIORITY_IN_USE_AT_SWAP error is signalled and the swap does not take /// place. This could only happen if the swap partner is not currently mapped. /// /// It is legal for a thread to swap its own priority with another thread. The @@ -889,13 +952,13 @@ ssx_thread_at_priority(SsxThreadPriority priority, /// actually change priorities, or the cases that assign new priorities to /// suspended, completed or deleted threads. /// -/// \retval -SSX_ILLEGAL_CONTEXT_THREAD the API was called from a critical -/// interrupt context. +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD the API was called from a critical +/// interrupt context. /// -/// \retval -SSX_INVALID_THREAD_AT_SWAP1 One or both of \a thread_a and -/// \a thread_b is null (0) or otherwise invalid, +/// \retval -SSX_INVALID_THREAD_AT_SWAP1 One or both of \a thread_a and +/// \a thread_b is null (0) or otherwise invalid, /// -/// \retval -SSX_INVALID_THREAD_AT_SWAP2 the priorities of One or both of +/// \retval -SSX_INVALID_THREAD_AT_SWAP2 the priorities of One or both of /// \a thread_a and \a thread_b are invalid. /// /// \retval -SSX_INVALID_ARGUMENT One or both of the priorities @@ -912,50 +975,62 @@ ssx_thread_priority_swap(SsxThread* thread_a, SsxThread* thread_b) SsxThreadPriority priority_a, priority_b; int mapped_a, mapped_b; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); - SSX_ERROR_IF((thread_a == 0) || (thread_b == 0), - SSX_INVALID_THREAD_AT_SWAP1); + SSX_ERROR_IF((thread_a == 0) || (thread_b == 0), + SSX_INVALID_THREAD_AT_SWAP1); } ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); - if (thread_a != thread_b) { + if (thread_a != thread_b) + { mapped_a = __ssx_thread_is_mapped(thread_a); mapped_b = __ssx_thread_is_mapped(thread_b); priority_a = thread_a->priority; priority_b = thread_b->priority; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { int priority_in_use; SSX_ERROR_IF_CRITICAL((priority_a > SSX_THREADS) || (priority_b > SSX_THREADS), SSX_INVALID_THREAD_AT_SWAP2, &ctx); - priority_in_use = + priority_in_use = (mapped_a && !mapped_b && (__ssx_thread_at_priority(priority_b) != 0)) || - (!mapped_a && mapped_b && + (!mapped_a && mapped_b && (__ssx_thread_at_priority(priority_a) != 0)); - SSX_ERROR_IF_CRITICAL(priority_in_use, - SSX_PRIORITY_IN_USE_AT_SWAP, &ctx); + SSX_ERROR_IF_CRITICAL(priority_in_use, + SSX_PRIORITY_IN_USE_AT_SWAP, &ctx); } - if (mapped_a) { + if (mapped_a) + { __ssx_thread_unmap(thread_a); } - if (mapped_b) { + + if (mapped_b) + { __ssx_thread_unmap(thread_b); - } + } + thread_a->priority = priority_b; thread_b->priority = priority_a; - if (mapped_a) { + + if (mapped_a) + { __ssx_thread_map(thread_a); } - if (mapped_b) { + + if (mapped_b) + { __ssx_thread_map(thread_b); } + __ssx_schedule(); } diff --git a/src/ssx/ssx/ssx_thread_init.c b/src/ssx/ssx/ssx_thread_init.c index 3fca442..8db8513 100644 --- a/src/ssx/ssx/ssx_thread_init.c +++ b/src/ssx/ssx/ssx_thread_init.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -76,31 +76,32 @@ /// \retval 0 Successful completion /// /// \retval -SSX_INVALID_THREAD_AT_CREATE The \a thread is a null (0) pointer. -/// +/// /// \retval -SSX_ILLEGAL_CONTEXT The API was called from a critical interrupt -/// context. +/// context. /// /// \retval -SSX_INVALID_ARGUMENT_THREAD1 the \a thread_routine is null (0) /// -/// \retval -SSX_INVALID_ARGUMENT_THREAD2 the \a priority is invalid, +/// \retval -SSX_INVALID_ARGUMENT_THREAD2 the \a priority is invalid, /// -/// \retval -SSX_INVALID_ARGUMENT_THREAD3 the stack area wraps around +/// \retval -SSX_INVALID_ARGUMENT_THREAD3 the stack area wraps around /// the end of memory. /// /// \retval -SSX_STACK_OVERFLOW The stack area at thread creation is smaller /// than the minimum safe size. int -ssx_thread_create(SsxThread *thread, +ssx_thread_create(SsxThread* thread, SsxThreadRoutine thread_routine, - void *arg, + void* arg, SsxAddress stack, size_t stack_size, SsxThreadPriority priority) { int rc; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_CREATE); SSX_ERROR_IF((thread_routine == 0) || @@ -109,25 +110,34 @@ ssx_thread_create(SsxThread *thread, } rc = __ssx_stack_init(&stack, &stack_size); - if (rc) { + + if (rc) + { return rc; } thread->saved_stack_pointer = stack; thread->stack_base = stack; - if (SSX_STACK_DIRECTION < 0) { + if (SSX_STACK_DIRECTION < 0) + { thread->stack_limit = stack - stack_size; - if (SSX_ERROR_CHECK_API) { + + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(thread->stack_limit > thread->stack_base, SSX_INVALID_ARGUMENT_THREAD2); } - } else { + } + else + { thread->stack_limit = stack + stack_size; - if (SSX_ERROR_CHECK_API) { + + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(thread->stack_limit < thread->stack_base, SSX_INVALID_ARGUMENT_THREAD3); } @@ -138,25 +148,25 @@ ssx_thread_create(SsxThread *thread, thread->state = SSX_THREAD_STATE_SUSPENDED_RUNNABLE; thread->flags = 0; - ssx_timer_create_nonpreemptible(&(thread->timer), - __ssx_thread_timeout, - (void *)thread); + ssx_timer_create_nonpreemptible(&(thread->timer), + __ssx_thread_timeout, + (void*)thread); __ssx_thread_context_initialize(thread, thread_routine, arg); return rc; } - - - - - - - + + + + + + + diff --git a/src/ssx/ssx/ssx_timer_core.c b/src/ssx/ssx/ssx_timer_core.c index d51c166..dd95812 100644 --- a/src/ssx/ssx/ssx_timer_core.c +++ b/src/ssx/ssx/ssx_timer_core.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -89,7 +89,7 @@ #include "ssx.h" -// This routine is only used in this file, and will always be called in +// This routine is only used in this file, and will always be called in // critical section. static inline int @@ -113,24 +113,30 @@ timer_active(SsxTimer* timer) // timeout. This will happen naturally when the current timeout expires. int -__ssx_timer_cancel(SsxTimer *timer) +__ssx_timer_cancel(SsxTimer* timer) { int rc; SsxDeque* timer_deque = (SsxDeque*)timer; SsxTimeQueue* tq = &__ssx_time_queue; - if (!timer_active(timer)) { + if (!timer_active(timer)) + { rc = -SSX_TIMER_NOT_ACTIVE; - } else { + } + else + { - if (timer_deque == tq->cursor) { + if (timer_deque == tq->cursor) + { tq->cursor = tq->cursor->next; } + ssx_deque_delete(timer_deque); rc = 0; } + return rc; } @@ -151,25 +157,29 @@ __ssx_timer_schedule(SsxTimer* timer) { SsxTimeQueue* tq = &__ssx_time_queue; - if (!timer_active(timer)) { + if (!timer_active(timer)) + { ssx_deque_push_back((SsxDeque*)tq, (SsxDeque*)timer); } - if (timer->timeout < tq->next_timeout) { + if (timer->timeout < tq->next_timeout) + { tq->next_timeout = timer->timeout; - if (tq->cursor == 0) { + + if (tq->cursor == 0) + { __ssx_schedule_hardware_timeout(tq->next_timeout); } } } - + // The tickless timer mechanism has timed out. Note that due to timer // deletions and other factors, there may not actually be a timer in the queue // that has timed out - but it doesn't matter (other than for efficiency). // // Noncritical interrupts are (must be) disabled at entry, and this invariant -// is checked. This routine must not be entered reentrantly. +// is checked. This routine must not be entered reentrantly. // // First, time out any timers that have expired. Timers in the queue are // unordered, so we have to check every one. Since passing through the @@ -190,7 +200,7 @@ __ssx_timer_schedule(SsxTimer* timer) // handlers may invoke time queue operations, we need to establish a pointer // to the next entry to be examined (tq->cursor) before enabling interupts. // It's possible that this pointer will be changed by other interrupt handlers -// that cancel the timer pointed to by tq->cursor. +// that cancel the timer pointed to by tq->cursor. // // The main loop iterates on the SsxDeque form of the time queue, casting each // element back up to the SsxTimer as it is processed. @@ -206,23 +216,28 @@ __ssx_timer_handler() tq = &__ssx_time_queue; - if (SSX_ERROR_CHECK_KERNEL) { - if (tq->cursor != 0) { + if (SSX_ERROR_CHECK_KERNEL) + { + if (tq->cursor != 0) + { SSX_PANIC(SSX_TIMER_HANDLER_INVARIANT); } } - while ((now = ssx_timebase_get()) >= tq->next_timeout) { + while ((now = ssx_timebase_get()) >= tq->next_timeout) + { tq->next_timeout = SSX_TIMEBASE_MAX; timer_deque = ((SsxDeque*)tq)->next; - while (timer_deque != (SsxDeque*)tq) { - + while (timer_deque != (SsxDeque*)tq) + { + timer = (SsxTimer*)timer_deque; tq->cursor = timer_deque->next; - if (timer->timeout <= now) { + if (timer->timeout <= now) + { // The timer timed out. It is removed from the queue unless // it is a peridic timer that needs to be rescheduled. We do @@ -235,26 +250,37 @@ __ssx_timer_handler() // we go ahead and open up to interrupts after the callback if // the callback itself was not preemptible. - if (timer->period == 0) { + if (timer->period == 0) + { ssx_deque_delete(timer_deque); - } else { + } + else + { timer->timeout += timer->period; tq->next_timeout = MIN(timer->timeout, tq->next_timeout); } callback = timer->callback; - if (callback) { - if (timer->options & SSX_TIMER_CALLBACK_PREEMPTIBLE) { + + if (callback) + { + if (timer->options & SSX_TIMER_CALLBACK_PREEMPTIBLE) + { ssx_interrupt_preemption_enable(); callback(timer->arg); - } else { + } + else + { callback(timer->arg); ssx_interrupt_preemption_enable(); } - } + } + ssx_interrupt_preemption_disable(); - } else { + } + else + { // This timer has not timed out. Its timeout will simply // participate in the computation of the next timeout. For @@ -269,7 +295,7 @@ __ssx_timer_handler() timer_deque = tq->cursor; } } - + tq->cursor = 0; // Finally, reschedule the next timeout @@ -293,7 +319,7 @@ __ssx_timer_handler() /// timer that is not rescheduled. /// /// Once created with ssx_timer_create() a timer can be \e scheduled, which -/// queues the timer in the kernel time queue. It is not an error to call +/// queues the timer in the kernel time queue. It is not an error to call /// ssx_timer_schedule() on a timer that is already scheduled in the time /// queue - the timer is simply rescheduled with the new characteristics. /// @@ -301,23 +327,24 @@ __ssx_timer_handler() /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_TIMER_AT_SCHEDULE A a null (0) pointer was provided as +/// \retval -SSX_INVALID_TIMER_AT_SCHEDULE A a null (0) pointer was provided as /// the \a timer argument. /// -/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical -/// interrupt context. +/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical +/// interrupt context. int -ssx_timer_schedule_absolute(SsxTimer *timer, +ssx_timer_schedule_absolute(SsxTimer* timer, SsxTimebase timeout, SsxInterval period) - + { SsxMachineContext ctx; ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(timer == 0, SSX_INVALID_TIMER_AT_SCHEDULE); SSX_ERROR_IF(__ssx_kernel_context_critical_interrupt(), SSX_ILLEGAL_CONTEXT_TIMER); @@ -354,15 +381,15 @@ ssx_timer_schedule_absolute(SsxTimer *timer, /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_TIMER_AT_SCHEDULE A a null (0) pointer was provided as +/// \retval -SSX_INVALID_TIMER_AT_SCHEDULE A a null (0) pointer was provided as /// the \a timer argument. /// -/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical -/// interrupt context. +/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical +/// interrupt context. int -ssx_timer_schedule(SsxTimer *timer, - SsxInterval interval, +ssx_timer_schedule(SsxTimer* timer, + SsxInterval interval, SsxInterval period) { return ssx_timer_schedule_absolute(timer, @@ -375,13 +402,13 @@ ssx_timer_schedule(SsxTimer *timer, /// /// \param timer The SsxTimer to cancel. /// -/// Timers can be canceled at any time. It is never an error to call +/// Timers can be canceled at any time. It is never an error to call /// ssx_timer_cancel() on an SsxTimer object after it is created. Memory used /// by an SsxTimer can be safely reused for another purpose after a successful /// call ofssx_timer_cancel(). /// /// Return values other than SSX_OK (0) are not necessarily errors; see \ref -/// ssx_errors +/// ssx_errors /// /// The following return codes are non-error codes: /// @@ -395,17 +422,18 @@ ssx_timer_schedule(SsxTimer *timer, /// /// \retval -SSX_INVALID_TIMER_AT_CANCEL The \a timer is a null (0) pointer. /// -/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical -/// interrupt context. +/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical +/// interrupt context. /// int -ssx_timer_cancel(SsxTimer *timer) +ssx_timer_cancel(SsxTimer* timer) { SsxMachineContext ctx; int rc = SSX_OK; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); SSX_ERROR_IF(timer == 0, SSX_INVALID_TIMER_AT_CANCEL); } @@ -447,19 +475,23 @@ ssx_timer_cancel(SsxTimer *timer) /// \retval -SSX_INVALID_TIMER_AT_INFO The \a timer is a null (0) pointer. int -ssx_timer_info_get(SsxTimer *timer, - SsxTimebase *timeout, - int *active) - +ssx_timer_info_get(SsxTimer* timer, + SsxTimebase* timeout, + int* active) + { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(timer == 0, SSX_INVALID_TIMER_AT_INFO); } - if (timeout) { + if (timeout) + { *timeout = timer->timeout; } - if (active) { + + if (active) + { *active = timer_active(timer); } diff --git a/src/ssx/ssx/ssx_timer_init.c b/src/ssx/ssx/ssx_timer_init.c index e944fd1..9dc7930 100644 --- a/src/ssx/ssx/ssx_timer_init.c +++ b/src/ssx/ssx/ssx_timer_init.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,12 +40,13 @@ // Implementation of timer creation static int -_ssx_timer_create(SsxTimer *timer, +_ssx_timer_create(SsxTimer* timer, SsxTimerCallback callback, - void *arg, + void* arg, int options) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((timer == 0), SSX_INVALID_TIMER_AT_CREATE); } @@ -71,7 +72,7 @@ _ssx_timer_create(SsxTimer *timer, /// Once created with ssx_timer_create() a timer can be scheduled with /// ssx_timer_schedule() or ssx_timer_schedule_absolute(), which queues the /// timer in the kernel time queue. Timers can be cancelled by a call of -/// ssx_timer_cancel(). +/// ssx_timer_cancel(). /// /// Timers created with ssx_timer_create() are always run as noncritical /// interrupt handlers with interrupt preemption enabled. Timer callbacks are @@ -88,12 +89,12 @@ _ssx_timer_create(SsxTimer *timer, /// /// \retval -SSX_INVALID_TIMER_AT_CREATE The \a timer is a null (0) pointer. -int -ssx_timer_create(SsxTimer *timer, +int +ssx_timer_create(SsxTimer* timer, SsxTimerCallback callback, - void *arg) + void* arg) { - return _ssx_timer_create(timer, callback, arg, + return _ssx_timer_create(timer, callback, arg, SSX_TIMER_CALLBACK_PREEMPTIBLE); } @@ -135,10 +136,10 @@ ssx_timer_create(SsxTimer *timer, /// /// \retval -SSX_INVALID_TIMER_AT_CREATE The \a timer is a null (0) pointer. -int -ssx_timer_create_nonpreemptible(SsxTimer *timer, +int +ssx_timer_create_nonpreemptible(SsxTimer* timer, SsxTimerCallback callback, - void *arg) + void* arg) { return _ssx_timer_create(timer, callback, arg, 0); } diff --git a/src/ssx/ssx/ssxssxfiles.mk b/src/ssx/ssx/ssxssxfiles.mk index fc5db57..2aa70b6 100644 --- a/src/ssx/ssx/ssxssxfiles.mk +++ b/src/ssx/ssx/ssxssxfiles.mk @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2014,2015 +# Contributors Listed Below - COPYRIGHT 2014,2016 # [+] International Business Machines Corp. # # diff --git a/src/ssx/trace/Makefile b/src/ssx/trace/Makefile index 5506b32..a822a78 100644 --- a/src/ssx/trace/Makefile +++ b/src/ssx/trace/Makefile @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2015 +# Contributors Listed Below - COPYRIGHT 2015,2016 # [+] International Business Machines Corp. # # diff --git a/src/ssx/trace/ssx_trace.h b/src/ssx/trace/ssx_trace.h index 3f4505f..6a2c3e6 100644 --- a/src/ssx/trace/ssx_trace.h +++ b/src/ssx/trace/ssx_trace.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -32,24 +32,24 @@ /// \file ssx_trace.h /// \brief Macros and declarations for the SSX Firmware Tracing Facility. -/// +/// #include <stdint.h> #define SSX_TRACE_VERSION 2 #ifndef SSX_TRACE_SZ -#define SSX_TRACE_SZ 256 + #define SSX_TRACE_SZ 256 #endif //Fail compilation if size is not a power of 2 #if ((SSX_TRACE_SZ - 1) & SSX_TRACE_SZ) -#error "SSX_TRACE_SZ is not a power of two!!!" + #error "SSX_TRACE_SZ is not a power of two!!!" #endif //Fail compilation if size is smaller than 64 bytes #if (SSX_TRACE_SZ < 64) -#error "SSX_TRACE_SZ must be at least 64 bytes!!!" + #error "SSX_TRACE_SZ must be at least 64 bytes!!!" #endif //Mask for calculating offsets into the trace circular buffer @@ -61,9 +61,9 @@ #define PPC_IMG_STRING STRINGIFY(IMAGE_NAME) #ifdef SSX_TRACE_HASH_PREFIX -#if (SSX_TRACE_HASH_PREFIX > 0xffff) -#error SSX_TRACE_HASH_PREFIX must be defined as a 16 bit constant value -#endif + #if (SSX_TRACE_HASH_PREFIX > 0xffff) + #error SSX_TRACE_HASH_PREFIX must be defined as a 16 bit constant value + #endif #endif //SSX_TRACE_HASH_PREFIX //This provides a 128ns tick (assuming a 32ns clock period) @@ -94,7 +94,7 @@ //are out of order it will result in a very large difference. To solve this //problem, any time that the parser code sees a very large difference (larger //than SSX_TRACE_MTBT) it will treat it as a negative number. -#define SSX_TRACE_MTBT (0xfffffffful - 31250000) +#define SSX_TRACE_MTBT (0xfffffffful - 31250000) #define SSX_TRACE_MAX_PARMS 4 @@ -107,9 +107,9 @@ //(The trace version does not need to change if this changes as long // as it remains less than SSX_TRACE_MAX_BINARY) #if (SSX_TRACE_SZ <= 256) -#define SSX_TRACE_CLIPPED_BINARY_SZ SSX_TRACE_SZ / 2 + #define SSX_TRACE_CLIPPED_BINARY_SZ SSX_TRACE_SZ / 2 #else -#define SSX_TRACE_CLIPPED_BINARY_SZ SSX_TRACE_MAX_BINARY + #define SSX_TRACE_CLIPPED_BINARY_SZ SSX_TRACE_MAX_BINARY #endif //Trace formats that are supported @@ -119,7 +119,7 @@ typedef enum SSX_TRACE_FORMAT_TINY, SSX_TRACE_FORMAT_BIG, SSX_TRACE_FORMAT_BINARY, -}SsxTraceFormat; +} SsxTraceFormat; //This combines the timestamp and the format bits into a //single 32 bit word. @@ -127,11 +127,13 @@ typedef union { struct { - uint32_t timestamp : SSX_TRACE_TS_BITS; - uint32_t format : SSX_TRACE_FORMAT_BITS; + uint32_t timestamp : + SSX_TRACE_TS_BITS; + uint32_t format : + SSX_TRACE_FORMAT_BITS; }; uint32_t word32; -}SsxTraceTime; +} SsxTraceTime; //SSX trace uses a 16 bit string format hash value typedef uint16_t SsxTraceHash; @@ -146,7 +148,7 @@ typedef union uint16_t parm; }; uint32_t word32; -}SsxTraceTinyParms; +} SsxTraceTinyParms; //A tiny trace fits within a single 8 byte word. This includes //the timestamp, format bits, hash id, and a 16 bit parameter. @@ -155,10 +157,10 @@ typedef union struct { SsxTraceTinyParms parms; - SsxTraceTime time_format; + SsxTraceTime time_format; }; uint64_t word64; -}SsxTraceTiny; +} SsxTraceTiny; //Larger traces that require a 32 bit parameter or more than one //parameter use the big trace format. The number of parms and @@ -174,17 +176,17 @@ typedef union uint8_t num_parms; }; uint32_t word32; -}SsxTraceBigParms; +} SsxTraceBigParms; typedef union { struct { SsxTraceBigParms parms; - SsxTraceTime time_format; + SsxTraceTime time_format; }; uint64_t word64; -}SsxTraceBig; +} SsxTraceBig; //Binary traces are handled in a similar fashion to big traces, except //that instead of having a number of parameters, we have number of bytes. @@ -197,7 +199,7 @@ typedef union uint8_t num_bytes; }; uint32_t word32; -}SsxTraceBinaryParms; +} SsxTraceBinaryParms; typedef union { @@ -207,7 +209,7 @@ typedef union SsxTraceTime time_format; }; uint64_t word64; -}SsxTraceBinary; +} SsxTraceBinary; //This is a generic structure that can be used to retrieve data //for tiny, big, and binary formatted entries. @@ -228,7 +230,7 @@ typedef union SsxTraceTime time_format; }; uint64_t word64; -}SsxTraceGeneric; +} SsxTraceGeneric; //This is a format that might be used in the future for tracing //a 64 bit timestamp so that we don't fill up the buffer with periodic @@ -242,7 +244,7 @@ typedef union SsxTraceTime time_format; }; uint64_t word64; -}SsxTraceTime64; +} SsxTraceTime64; #endif //It would probably be more accurate to call this a footer since it @@ -255,7 +257,7 @@ typedef union SsxTraceBinary binary; SsxTraceBig big; SsxTraceTiny small; -}SsxTraceEntryFooter; +} SsxTraceEntryFooter; //This is the data that is updated (in the buffer header) every time we add @@ -268,7 +270,7 @@ typedef union uint32_t offset; }; uint64_t word64; -}SsxTraceState; +} SsxTraceState; #define SSX_TRACE_IMG_STR_SZ 16 @@ -296,7 +298,7 @@ typedef struct //circular trace buffer uint8_t cb[SSX_TRACE_SZ]; -}SsxTraceBuffer; +} SsxTraceBuffer; extern SsxTraceBuffer g_ssx_trace_buf; extern size_t g_ssx_trace_buf_size; diff --git a/src/ssx/trace/ssx_trace_big.c b/src/ssx/trace/ssx_trace_big.c index 4a9bdb5..49e03be 100644 --- a/src/ssx/trace/ssx_trace_big.c +++ b/src/ssx/trace/ssx_trace_big.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -41,7 +41,7 @@ #if (SSX_TRACE_SUPPORT && SSX_TIMER_SUPPORT) void ssx_trace_big(uint32_t i_hash_and_count, - uint64_t i_parm1, uint64_t i_parm2) + uint64_t i_parm1, uint64_t i_parm2) { SsxTraceBig footer; SsxTraceBig* footer_ptr; @@ -100,6 +100,7 @@ void ssx_trace_big(uint32_t i_hash_and_count, footer_ptr = (SsxTraceBig*)ptr64; ptr64 = (uint64_t*)&g_ssx_trace_buf.cb[cur_offset & SSX_TRACE_CB_MASK]; *ptr64 = i_parm1; + if(parm_size > 8) { ptr64 = (uint64_t*)&g_ssx_trace_buf.cb[(cur_offset + 8) & SSX_TRACE_CB_MASK]; diff --git a/src/ssx/trace/ssx_trace_binary.c b/src/ssx/trace/ssx_trace_binary.c index f1d1db6..fd80907 100644 --- a/src/ssx/trace/ssx_trace_binary.c +++ b/src/ssx/trace/ssx_trace_binary.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/trace/ssx_trace_core.c b/src/ssx/trace/ssx_trace_core.c index de9d309..10f323f 100644 --- a/src/ssx/trace/ssx_trace_core.c +++ b/src/ssx/trace/ssx_trace_core.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -46,7 +46,8 @@ void ssx_trace_timer_callback(void* arg); #if (SSX_TRACE_SUPPORT && SSX_TIMER_SUPPORT) //Static initialization of the trace timer -SsxTimer g_ssx_trace_timer = { +SsxTimer g_ssx_trace_timer = +{ .deque = SSX_DEQUE_ELEMENT_INIT(), .timeout = 0, .callback = ssx_trace_timer_callback, @@ -89,7 +90,7 @@ void ssx_trace_tiny(uint32_t i_parm) tb64 = ssx_ext_timebase_get(); state.tbu32 = tb64 >> 32; footer.time_format.word32 = tb64 & 0x00000000ffffffffull; - + footer.time_format.format = SSX_TRACE_FORMAT_TINY; //The following operations must be done atomically @@ -124,8 +125,8 @@ void ssx_trace_timer_callback(void* arg) // restart the timer ssx_timer_schedule(&g_ssx_trace_timer, - SSX_TRACE_TIMER_PERIOD, - 0); + SSX_TRACE_TIMER_PERIOD, + 0); } // Use this function to synchronize the timebase between multiple Processors. @@ -163,7 +164,7 @@ void ssx_trace_init(uint32_t timebase_frequency_hz, } ////Needed for easy cache flush of trace buffer -size_t g_ssx_trace_buf_size=sizeof(g_ssx_trace_buf); +size_t g_ssx_trace_buf_size = sizeof(g_ssx_trace_buf); #endif diff --git a/src/ssx/trace/ssxtracefiles.mk b/src/ssx/trace/ssxtracefiles.mk index dc3d058..46949cd 100644 --- a/src/ssx/trace/ssxtracefiles.mk +++ b/src/ssx/trace/ssxtracefiles.mk @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2015 +# Contributors Listed Below - COPYRIGHT 2015,2016 # [+] International Business Machines Corp. # # |