summaryrefslogtreecommitdiffstats
path: root/src/ssx/pgp/pgp_async_pore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssx/pgp/pgp_async_pore.c')
-rwxr-xr-xsrc/ssx/pgp/pgp_async_pore.c644
1 files changed, 0 insertions, 644 deletions
diff --git a/src/ssx/pgp/pgp_async_pore.c b/src/ssx/pgp/pgp_async_pore.c
deleted file mode 100755
index 5f9b425..0000000
--- a/src/ssx/pgp/pgp_async_pore.c
+++ /dev/null
@@ -1,644 +0,0 @@
-// $Id: pgp_async_pore.c,v 1.5 2014/05/14 13:35:43 bcbrock Exp $
-// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async_pore.c,v $
-//-----------------------------------------------------------------------------
-// *! (C) Copyright International Business Machines Corp. 2013
-// *! All Rights Reserved -- Property of IBM
-// *! *** IBM Confidential ***
-//-----------------------------------------------------------------------------
-
-/// \file pgp_async_pore.c
-/// \brief PgP "async" drivers for PORE engines
-
-#include "ssx.h"
-
-////////////////////////////////////////////////////////////////////////////
-// Global Data
-////////////////////////////////////////////////////////////////////////////
-
-// The PORE queue objects.
-
-PoreQueue G_pore_gpe0_queue;
-PoreQueue G_pore_gpe1_queue;
-PoreQueue G_pore_slw_queue;
-
-
-////////////////////////////////////////////////////////////////////////////
-// Local Data
-////////////////////////////////////////////////////////////////////////////
-
-/// PoreFlex entry point - See G_pore_flex_table.
-
-static uint32_t G_pore_flex_entry0 = PORE_BRAD_D0;
-
-
-/// Entry 0 of the PoreFlex branch table
-///
-/// This variable is the only thing we represent of the branch table for PORE
-/// flex requests. PoreFlex requests are forbidden from using PORE error
-/// handlers. Therefore they don't require the 60 redundant bytes of error
-/// handler entry points. They also only run trigger slot 0, and begin
-/// execution with a BRAD D0, so the only thing we represent is a single BRAD
-/// D0 instruction.
-
-static uint32_t* G_pore_flex_table = &G_pore_flex_entry0 - (PORE_ERROR_SLOTS * 3);
-
-
-////////////////////////////////////////////////////////////////////////////
-// PoreQueue
-////////////////////////////////////////////////////////////////////////////
-
-/// Create (initialize) a PoreQueue
-///
-/// \param queue An uninitialized of otherwise idle PoreQueue
-///
-/// \param engine The identifier of a PORE engine associated with this queue.
-///
-/// This API initializes the PoreQueue structure and also initializes the
-/// underlying PORE hardware to run in the OCC environment. Neither the
-/// branch table nor the error modes are specified here - those are considered
-/// application-specific functions that are set up each time a job is run on
-/// the engine.
-///
-/// \retval 0 Success
-///
-/// \retval -ASYNC_INVALID_OBJECT_PORE_QUEUE The \a queue was NULL (0).
-///
-/// \retval -ASYNC_INVALID_ENGINE_PORE The \a engine is not a (valid)
-/// PORE engine.
-
-int
-pore_queue_create(PoreQueue *queue, int engine)
-{
- pore_control_t control;
-
- if (SSX_ERROR_CHECK_API) {
- SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PORE_QUEUE);
- SSX_ERROR_IF(!(engine & ASYNC_ENGINE_PORE), ASYNC_INVALID_ENGINE_PORE);
- }
-
- async_queue_create(&(queue->queue), engine);
-
- switch (engine) {
-
- case ASYNC_ENGINE_PORE_GPE0:
- queue->oci_base = PORE_GPE0_OCI_BASE;
- queue->irq = PGP_IRQ_PORE_GPE0_COMPLETE;
- queue->error_irq = PGP_IRQ_PORE_GPE0_ERROR;
- queue->oci_master = OCI_MASTER_ID_PORE_GPE;
- break;
-
- case ASYNC_ENGINE_PORE_GPE1:
- queue->oci_base = PORE_GPE1_OCI_BASE;
- queue->irq = PGP_IRQ_PORE_GPE1_COMPLETE;
- queue->error_irq = PGP_IRQ_PORE_GPE1_ERROR;
- queue->oci_master = OCI_MASTER_ID_PORE_GPE;
- break;
-
- case ASYNC_ENGINE_PORE_SLW:
- queue->oci_base = PORE_SLW_OCI_BASE;
- queue->irq = PGP_IRQ_PORE_SW_COMPLETE;
- queue->error_irq = PGP_IRQ_PORE_SW_ERROR;
- queue->oci_master = OCI_MASTER_ID_PORE_SLW;
- break;
-
- default:
- SSX_PANIC(ASYNC_BUG_PORE_AT_CREATE);
- }
-
- // PORE engine setup
- //
- // Force the PORE to stop and set it up for OCC control. Neither the
- // breakpoint address nor the trap enable setting are modified in case
- // they are being controlled from Simics or a hardware debugger ab initio.
- //
- // Register field settings:
- //
- // The scanclk ratio is not modified.
- // The EXE-Trigger register is unlocked
- // The freeze action is not modified
- // Instruction parity is ignored
- // The PIB parity checking setting is not modified
- // The TRAP enable is not modified
- // The breakpoint address is not modified
-
- control.value = in64(queue->oci_base + PORE_CONTROL_OFFSET);
-
- control.fields.start_stop = 1;
- control.fields.lock_exe_trig= 0;
- control.fields.check_parity = 0;
-
- out64(queue->oci_base + PORE_CONTROL_OFFSET, control.value);
-
- return 0;
-}
-
-
-// The interrupt handler for asynchronous PORE errors
-//
-// The PORE interrupts are disabled here, then cleared and re-enabled when the
-// next job runs. This is to protect against "phantom" interrupts caused by
-// PORE freeze-on-checkstop behavior.
-
-SSX_IRQ_FAST2FULL(pore_async_error_handler, pore_async_error_handler_full);
-
-void
-pore_async_error_handler_full(void *arg, SsxIrqId irq, int priority)
-{
- PoreQueue* queue = (PoreQueue*)arg;
-
- ssx_irq_disable(queue->irq);
- ssx_irq_disable(queue->error_irq);
-
- async_error_handler((AsyncQueue *)arg, ASYNC_REQUEST_STATE_FAILED);
-}
-
-
-// The interrupt handler for asynchronous PORE requests
-//
-// The PORE interrupts are disabled here, then cleared and re-enabled when the
-// next job runs. This is to protect against "phantom" interrupts caused by
-// PORE freeze-on-checkstop behavior.
-//
-// Note that if the system checkstops and freezes the PORE we will get a
-// normal completion interrupt. Therefore we have to check to see if the
-// completion is associated with a freeze, and if so, fail the job.
-
-SSX_IRQ_FAST2FULL(pore_async_handler, pore_async_handler_full);
-
-void
-pore_async_handler_full(void *arg, SsxIrqId irq, int priority)
-{
- PoreQueue* queue = (PoreQueue*)arg;
- pore_status_t status;
-
- status.value = in64(queue->oci_base + PORE_STATUS_OFFSET);
- if (status.fields.freeze_action) {
-
- pore_async_error_handler_full(arg, irq, priority);
-
- } else {
-
- ssx_irq_disable(queue->irq);
- ssx_irq_disable(queue->error_irq);
-
- async_handler((AsyncQueue *)arg);
- }
-}
-
-
-////////////////////////////////////////////////////////////////////////////
-// PoreRequest
-////////////////////////////////////////////////////////////////////////////
-
-/// Create (initialize) the PoreRequest base class
-///
-/// \param request An uninitialized or otherwise idle PoreRequest.
-///
-/// \param queue An initialized PoreQueue
-///
-/// \param table The PORE branch table to install prior to kicking off the
-/// engine. All PoreFlex jobs use a common (stubbed) table. PoreFixed jobs
-/// must supply a fully-formed table.
-///
-/// \param error_mask The initial value of the PORE ERROR_MASK register to be
-/// installed before kicking off the engine.
-///
-/// \param entry_point The entry point address of the routine. For PoreFlex
-/// this entry point will be non-0 and will be inserted into D0, as PoreFlex
-/// jobs are kicked off by BRAD D0. For PoreFixed this parameter will be zero
-/// and ignored.
-///
-/// \param start_vector The TBAR start vector to execute. This will always be
-/// 0 for PoreFlex.
-///
-/// \param parameter The single 32-bit parameter to the PORE program. This
-/// value is stored in the low-order part of the \c EXE_TRIGGER register
-/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER
-/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as
-/// this is the hardware usage for hardware-initiated PORE-SLW routines.)
-///
-/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
-/// will be governed by a private watchdog timer that will cancel a queued job
-/// or kill a running job if the hardware operation does not complete before
-/// it times out.
-///
-/// \param callback The callback to execute when the PORE program completes,
-/// or NULL (0) to indicate no callback.
-///
-/// \param arg The parameter to the callback routine; ignored if the \a
-/// callback is NULL.
-///
-/// \param options Options to control request priority and callback context.
-///
-/// This routine has no way to know if the PoreRequest structure is currently
-/// in use, so this API should only be called on uninitialized or otherwise
-/// idle PoreRequest structures.
-///
-/// \retval 0 Success
-///
-/// \retval -ASYNC_INVALID_OBJECT_PORE_REQUEST The \a request was NULL (0)
-/// or the \a queue was NULL (0) or not a PoreQueue.
-///
-/// \retval -ASYNC_INVALID_ARGUMENT_PORE_REQUEST The \a start_vector is invalid or any of
-/// the parameters that represent OCI addresses are not 4-byte aligned, , or
-/// the \a table was null.
-///
-/// See async_request_create() for other errors that may be returned by this
-/// call.
-
-int
-pore_request_create(PoreRequest *request,
- PoreQueue *queue,
- PoreBraia* table,
- uint32_t error_mask,
- uint32_t entry_point,
- int start_vector,
- uint32_t parameter,
- SsxInterval timeout,
- AsyncRequestCallback callback,
- void *arg,
- int options)
-{
- AsyncQueue *async_queue = (AsyncQueue *)queue;
- int rc;
- pore_exe_trigger_t etr;
-
- if (SSX_ERROR_CHECK_API) {
- SSX_ERROR_IF(!(async_queue->engine & ASYNC_ENGINE_PORE),
- ASYNC_INVALID_OBJECT_PORE_REQUEST);
- SSX_ERROR_IF((start_vector < 0) ||
- (start_vector >= PORE_TRIGGER_SLOTS) ||
- ((uint32_t) table % 4) ||
- (entry_point % 4) ||
- (table == 0),
- ASYNC_INVALID_ARGUMENT_PORE_REQUEST);
- }
-
- rc = async_request_create(&(request->request),
- async_queue,
- pore_run_method,
- pore_error_method,
- timeout,
- callback,
- arg,
- options);
-
- if (!rc) {
- request->table = table;
- request->error_mask = error_mask;
- request->entry_point = entry_point;
- request->parameter = parameter;
- etr.value = 0;
- etr.fields.start_vector = start_vector;
- request->exe_trigger = etr.words.high_order;
- }
-
- return rc;
-}
-
-
-// Start a PoreRequest on a PORE
-//
-// \param async_request A PoreRequest upcast to an AsyncRequest.
-//
-// This is an internal API. At entry both the completion and error interrupts
-// are disabled and may show status that needs to be cleared before they are
-// re-enabled.
-//
-// This routine implements a simple procedure:
-//
-// - Check to make sure the PORE is not frozen due to a checkstop, and if so,
-// collect FFDC and immediately fail the job.
-//
-// Otherwise:
-//
-// - Reset the PORE engine to clear up any error status that may remain from
-// the last job .
-// - Install the TBAR (Table Base Address Register) from the request as an OCI
-// address
-// - Set the EMR (Error Mask Register) from the request
-// - Install the parameter (ETR[32:63])
-// - If the entry point is non-0 then this is a PoreFlex job that is kicked
-// off by a BRAD D0, and the entry point is installed in D0 as a full OCI
-// address.
-// - Clear pending interrupt status
-// - Hit ETR[0:31] to start the job.
-// - Enable interrupts.
-//
-// If the PORE is frozen due to a system checkstop we fail the job immediately
-// right here. Note that there is still a small window where the system may
-// checkstop and the PORE may freeze after this check. Unfortunately the PORE
-// design locks out register writes while frozen, and instead of reporting
-// write access attempts as bus errors, silently ignores them and simply sets
-// a FIR bit. Originally the "frozen" check was done last to shrink the
-// window, however this practically guarantees these FIRs in a checkstopped
-// system (which the FW team finds problematic), so the check was moved to the
-// front of the procedure. (SW256621).
-//
-// Note that PORE interrupts remain masked unless the job starts successfully.
-
-int
-pore_run_method(AsyncRequest *async_request)
-{
- PoreQueue *queue = (PoreQueue*)(async_request->queue);
- PoreRequest *request = (PoreRequest*)async_request;
- pore_status_t status;
- pore_reset_t reset;
- uint32_t oci_base;
- int rc;
-
- oci_base = queue->oci_base;
-
- status.value = in64(oci_base + PORE_STATUS_OFFSET);
- if (status.fields.freeze_action) {
-
- pore_error_method(async_request);
- async_request->completion_state = ASYNC_REQUEST_STATE_FAILED;
- rc = -ASYNC_REQUEST_COMPLETE;
-
- } else {
-
- reset.value = 0;
- reset.fields.fn_reset = 1;
- out32(oci_base + PORE_RESET_OFFSET, reset.value);
-
- out32(oci_base + PORE_TABLE_BASE_ADDR_OFFSET, PORE_ADDRESS_SPACE_OCI);
- out32(oci_base + PORE_TABLE_BASE_ADDR_OFFSET + 4,
- (uint32_t)(request->table));
- out32(oci_base + PORE_ERROR_MASK_OFFSET, request->error_mask);
- out32(oci_base + PORE_EXE_TRIGGER_OFFSET + 4, request->parameter);
-
- if (request->entry_point != 0) {
- out32(oci_base + PORE_SCRATCH1_OFFSET, PORE_ADDRESS_SPACE_OCI);
- out32(oci_base + PORE_SCRATCH1_OFFSET + 4, request->entry_point);
- }
-
- ssx_irq_status_clear(queue->irq);
- ssx_irq_status_clear(queue->error_irq);
-
- out32(oci_base + PORE_EXE_TRIGGER_OFFSET, request->exe_trigger);
-
- ssx_irq_enable(queue->irq);
- ssx_irq_enable(queue->error_irq);
- rc = 0;
- }
-
- return rc;
-}
-
-
-// PORE FFDC collection
-//
-// \param async_request A PoreRequest upcast to an AsyncRequest
-//
-// This is an internal API, called from an interrupt context when a PORE
-// engine signals an error interrupt. See the comments for PoreFfdc for a
-// description of why this particular set of data is collected.
-//
-// PORE error handling procedure:
-//
-// - Collect FFDC from the PLB arbiter
-//
-// - Collect FFDC from the failing engine
-//
-// Currently all PORE errors are treated as recoverable
-
-/// \todo Consider analyzing the errors to determine if the error should be
-/// considered fatal.
-
-int
-pore_error_method(AsyncRequest *async_request)
-{
- PoreQueue *queue = (PoreQueue*)(async_request->queue);
- PoreRequest *request = (PoreRequest*)async_request;
- uint32_t oci_base;
- PoreFfdc* ffdc;
-
- oci_base = queue->oci_base;
- ffdc = &(request->ffdc);
-
- oci_ffdc(&(ffdc->oci_ffdc), queue->oci_master);
-
- ffdc->debug[0] = in64(oci_base + PORE_DBG0_OFFSET);
- ffdc->debug[1] = in64(oci_base + PORE_DBG1_OFFSET);
- ffdc->address[0] = in32(oci_base + PORE_OCI_BASE_ADDRESS0_OFFSET + 4);
- ffdc->address[1] = in32(oci_base + PORE_OCI_BASE_ADDRESS1_OFFSET + 4);
- ffdc->ibuf[0] = in32(oci_base + PORE_IBUF_01_OFFSET);
- ffdc->ibuf[1] = in32(oci_base + PORE_IBUF_01_OFFSET + 4);
- ffdc->ibuf[2] = in32(oci_base + PORE_IBUF_2_OFFSET);
-
- return 0;
-}
-
-
-/// Create (initialize) a PoreBraia branch table entry
-///
-/// \param instr A pointer to the BRAIA instruction to initialize. Use the
-/// macros PORE_ERROR_BRANCH(table, n) and PORE_ENTRY_BRANCH(table, n) to
-/// select one of 5 error branches or one of 16 entry point branches in a PORE
-/// branch table.
-///
-/// \param address The 32-bit OCI address of the error routine or entry point.
-///
-/// This routine initializes the given entry of a PORE branch table with an
-/// OCI-based BRAIA instruction, them flushes the entry from the D-Cache.
-
-// Note that we don't know the alignment of the jump table, so we need to
-// flush both the first and last jump address to ensure that the BRAI is
-// completely flushed. This assumes (correctly) that uint32_t are at least
-// 4-byte aligned.
-
-void
-pore_braia_create(PoreBraia* instr, uint32_t address) {
- instr->word[0] = PORE_BRAI;
- instr->word[1] = PORE_ADDRESS_SPACE_OCI;
- instr->word[2] = address;
- dcache_flush_line(&(instr->word[0]));
- dcache_flush_line(&(instr->word[2]));
-}
-
-
-////////////////////////////////////////////////////////////////////////////
-// PoreFlex
-////////////////////////////////////////////////////////////////////////////
-
-/// Create (initialize) a flex-mode PORE request
-///
-/// \param request An uninitialized or otherwise idle PoreFlex.
-///
-/// \param queue A pointer to a PoreQueue
-///
-/// \param entry_point The entry point of the PORE program. This must be a
-/// 32-bit, 4-byte aligned byte address in OCI space. The PoreEntryPoint
-/// typedef is provided to declare external PORE entry points. Note that an \a
-/// entry_point of 0 is considered an error - although it \e is conceivably a
-/// legal OCI address in mainstore via the PBA.
-///
-/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
-/// will be governed by a private watchdog timer that will cancel a queued job
-/// or kill a running job if the hardware operation does not complete before
-/// it times out.
-///
-/// \param parameter The single 32-bit parameter to the PORE program. This
-/// value is stored in the high-order part of the \c EXE_TRIGGER register
-/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER
-/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as
-/// this is the hardware usage for hardware-initiated PORE-SLW routines.)
-///
-/// \param callback The callback to execute when the PORE program completes,
-/// or NULL (0) to indicate no callback.
-///
-/// \param arg The parameter to the callback routine; ignored if the \a
-/// callback is NULL.
-///
-/// \param options Options to control request priority and callback context.
-///
-/// This routine has no way to know if the PoreFlex structure is currently
-/// in use, so this API should only be called on uninitialized or
-/// otherwise idle PoreFlex structures.
-///
-/// \retval 0 Success
-///
-/// See pore_request_create() for error return codes that may be returned by
-/// this call.
-
-int
-pore_flex_create(PoreFlex *request,
- PoreQueue *queue,
- PoreEntryPoint entry_point,
- uint32_t parameter,
- SsxInterval timeout,
- AsyncRequestCallback callback,
- void *arg,
- int options)
-{
- uint32_t emr;
-
- // PoreFlex jobs run w/o error handlers, and ignore sleeping cores. All
- // errors are signalled on both error outputs of all PORE engines.
-
- emr = (PORE_ERROR_MASK_ENABLE_ERR_OUTPUT0 |
- PORE_ERROR_MASK_ENABLE_ERR_OUTPUT1 |
- PORE_ERROR_MASK_ENABLE_ERR_OUTPUT2 |
- PORE_ERROR_MASK_ENABLE_ERR_OUTPUT3 |
- PORE_ERROR_MASK_ENABLE_ERR_OUTPUT4 |
- PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT0 |
- PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT1 |
- PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT2 |
- PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT3 |
- PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT4 |
- PORE_ERROR_MASK_STOP_EXE_ON_ERROR0 |
- PORE_ERROR_MASK_STOP_EXE_ON_ERROR1 |
- PORE_ERROR_MASK_STOP_EXE_ON_ERROR2 |
- PORE_ERROR_MASK_STOP_EXE_ON_ERROR3 |
- PORE_ERROR_MASK_STOP_EXE_ON_ERROR4) >> 32;
-
- return pore_request_create((PoreRequest*)request,
- queue,
- (PoreBraia*)G_pore_flex_table,
- emr,
- (uint32_t)entry_point,
- 0,
- parameter,
- timeout,
- callback,
- arg,
- options);
-}
-
-
-////////////////////////////////////////////////////////////////////////////
-// PoreFixed
-////////////////////////////////////////////////////////////////////////////
-
-/// Create (initialize) a fixed-mode PORE request
-///
-/// \param request An uninitialized or otherwise idle PoreFixed request.
-///
-/// \param queue A PoreQueue capable of running fixed requests.
-///
-/// \param table A PORE branch table containing all of the error handler and
-/// entry point assignments required for the request.
-///
-/// \param error_mask A value that will be loaded into the high-order 32-bits
-/// of the PORE Error Mask Register to control error behavior.
-///
-/// \param start_vector The branch table slot reserved for this request.
-///
-/// \param parameter The single 32-bit parameter to the PORE program. This
-/// value is stored in the high-order part of the \c EXE_TRIGGER register
-/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER
-/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as
-/// this is the hardware usage for hardware-initiated PORE-SLW routines.)
-///
-/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
-/// will be governed by a private watchdog timer that will cancel a queued job
-/// or kill a running job if the hardware operation does not complete before
-/// it times out.
-///
-/// \param callback The callback to execute when the PORE program completes,
-/// or NULL (0) to indicate no callback.
-///
-/// \param arg The parameter to the callback routine; ignored if the \a
-/// callback is NULL.
-///
-/// \param options Options to control request priority and callback context.
-///
-/// This routine has no way to know if the PoreFixed structure is currently
-/// in use, so this API should only be called on uninitialized or
-/// otherwise idle PoreFlex structures.
-///
-/// \retval 0 Success
-///
-/// See pore_request_create() for error return codes that may be returned by
-/// this call.
-
-int
-pore_fixed_create(PoreFixed *request,
- PoreQueue *queue,
- PoreBraia* table,
- uint32_t error_mask,
- int start_vector,
- uint32_t parameter,
- SsxInterval timeout,
- AsyncRequestCallback callback,
- void *arg,
- int options)
-{
- return pore_request_create((PoreRequest*)request,
- queue,
- table,
- error_mask,
- 0,
- start_vector,
- parameter,
- timeout,
- callback,
- arg,
- options);
-}
-
-
-////////////////////////////////////////////////////////////////////////////
-// Initialization
-////////////////////////////////////////////////////////////////////////////
-
-// Due to the fact that PORE signals a "complete" interrupt on a freeze event
-// (i.e., a checkstop, even if PORE is not running), we can not enable PORE
-// interrupts globally. They need to be carefully managed to avoid "phantom
-// interrupt" panics from async_handler().
-
-void
-async_pore_initialize(PoreQueue *queue,int engine)
-{
- pore_queue_create(queue, engine);
- async_edge_handler_setup(pore_async_handler,
- (void *)queue,
- queue->irq, SSX_CRITICAL);
- async_edge_handler_setup(pore_async_error_handler,
- (void *)queue,
- queue->error_irq, SSX_CRITICAL);
-}
-
-
-
OpenPOWER on IntegriCloud