From 0ee0cf11ed50cf9c43d05a1ba2aa4f25801b6d97 Mon Sep 17 00:00:00 2001 From: Andres Lugo-Reyes Date: Tue, 10 Jan 2017 08:52:34 -0600 Subject: [PATCH] WOF: Function to calculate the desired VFRT Mainstore address Function also copies VFRT from Mainstore to SRAM and then sends the WOF VFRT IPC command to the PGPE Change-Id: I94c7d4bcc9179fce3f17c1b974a12186c67547c1 RTC: 130216 Depends-on: I2249777134608d9f79bdc85692a3acbf7907c3f5 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/34658 Tested-by: FSP CI Jenkins Reviewed-by: William A. Bryan --- src/occ_405/linkocc.cmd | 36 +++- src/occ_405/pgpe/pgpe_shared.h | 10 +- src/occ_405/wof/wof.c | 262 ++++++++++++++++++++++++++++ src/occ_405/wof/wof.h | 21 ++- src/occ_405/wof/wof_service_codes.h | 41 +++++ 5 files changed, 363 insertions(+), 7 deletions(-) create mode 100644 src/occ_405/wof/wof_service_codes.h diff --git a/src/occ_405/linkocc.cmd b/src/occ_405/linkocc.cmd index 1dbf362d..3c4556c3 100755 --- a/src/occ_405/linkocc.cmd +++ b/src/occ_405/linkocc.cmd @@ -533,14 +533,42 @@ SECTIONS #if EXECUTABLE_FREE_SPACE _DATA_SECTION_SIZE = . - _DATA_SECTION_BASE; __WRITEABLE_DATA_LEN__ = . - __WRITEABLE_DATA_ADDR__ ; - _EX_FREE_SECTION_SIZE = _GLOBAL_DATA_BASE - _EX_FREE_SECTION_BASE; + _EX_FREE_SECTION_SIZE = _PING_PONG_BUFFER_BASE - _EX_FREE_SECTION_BASE; #else - _DATA_SECTION_SIZE = _GLOBAL_DATA_BASE - _DATA_SECTION_BASE; - __WRITEABLE_DATA_LEN__ = _GLOBAL_DATA_BASE - __WRITEABLE_DATA_ADDR__ ; + _DATA_SECTION_SIZE = _PING_PONG_BUFFER_BASE - _DATA_SECTION_BASE; + __WRITEABLE_DATA_LEN__ = _PING_PONG_BUFFER_BASE - __WRITEABLE_DATA_ADDR__ ; _EX_FREE_SECTION_SIZE = 0; #endif - _SSX_FREE_END = _GLOBAL_DATA_BASE - 1; + _SSX_FREE_END = _PING_PONG_BUFFER_BASE - 1; + + + //////////////////////////////// + // Ping/Pong Buffer Section + // + // Contains two 256-byte buffers used to tell the PGPE which vfrt to use + // + //////////////////////////////// + __CUR_COUNTER__ = .; + _PING_PONG_BUFFER_BASE = 0xfffb3d00; + _PING_BUFFER_BASE = 0xfffb3d00; + _PING_BUFFER_SIZE = 0x100; + _PONG_BUFFER_BASE = 0xfffb3e00; + _PONG_BUFFER_SIZE = 0x100; + . = _PING_BUFFER_BASE; +#if !PPC405_MMU_SUPPORT + . = . - writethrough_offset; + _LMA = . + writethrough_offset; + .vfrt_ping_buffer . : AT(_LMA) {*(vfrt_ping_buffer) . = ALIGN(_PING_BUFFER_SIZE);} + _LMA = . + writethrough_offset; + .vfrt_pong_buffer . : AT(_LMA) {*(vfrt_pong_buffer) . = ALIGN(_PONG_BUFFER_SIZE);} + . = . + writethrough_offset; +#else + .vfrt_ping_buffer . : {*(vfrt_ping_buffer) . = ALIGN(_PING_BUFFER_SIZE);} > sram + .vfrt_pong_buffer . : {*(vfrt_pong_buffer) . = ALIGN(_PONG_BUFFER_SIZE);} > sram +#endif + . = __CUR_COUNTER__; + //////////////////////////////// diff --git a/src/occ_405/pgpe/pgpe_shared.h b/src/occ_405/pgpe/pgpe_shared.h index 0610953e..a037cd45 100644 --- a/src/occ_405/pgpe/pgpe_shared.h +++ b/src/occ_405/pgpe/pgpe_shared.h @@ -36,12 +36,18 @@ #define PGPE_WOF_TBLS_ADDR_OFFSET 0x50 #define PGPE_WOF_TBLS_LEN_OFFSET 0x54 +// Offset addresses of OCC-PGPE Shared SRAM pointers (relative to Shared SRAM ptr) +#define PGPE_SHARED_REQUESTED_ACTIVE_QUAD_UPDATE_OFFSET 0x18 + // PGPE Image Header Parameter addresses //Shared OCC-PGPE SRAM parameters #define PGPE_SHARED_SRAM_ADDR_PTR (PGPE_HEADER_ADDR + PGPE_SHARED_SRAM_ADDR_OFFSET) #define PGPE_SHARED_SRAM_SZ_PTR (PGPE_HEADER_ADDR + PGPE_SHARED_SRAM_SZ_OFFSET) + + + // A pointer to PGPE Beacon Address #define PGPE_BEACON_ADDR_PTR (PGPE_HEADER_ADDR + PGPE_BEACON_ADDR_OFFSET) @@ -49,7 +55,9 @@ #define PGPE_ACTIVE_QUAD_ADDR_PTR (PGPE_HEADER_ADDR + PGPE_ACTIVE_QUAD_ADDR_OFFSET) #define PGPE_WOF_TBLS_ADDR_PTR (PGPE_HEADER_ADDR + PGPE_WOF_TBLS_ADDR_OFFSET) #define PGPE_WOF_TBLS_LEN_PTR (PGPE_HEADER_ADDR + PGPE_WOF_TBLS_LEN_OFFSET) - +#define PGPE_SHARED_REQUESTED_ACTIVE_QUAD_UPDATE_PTR \ + (PGPE_SHARED_SRAM_ADDR_PTR + \ + PGPE_SHARED_REQUESTED_ACTIVE_QUAD_UPDATE_OFFSET) // PMMR (Pstates PM region) in HOMMR diff --git a/src/occ_405/wof/wof.c b/src/occ_405/wof/wof.c index bad31b67..4815213c 100644 --- a/src/occ_405/wof/wof.c +++ b/src/occ_405/wof/wof.c @@ -26,6 +26,10 @@ #include #include #include +#include +#include +#include +#include #include "wof.h" @@ -37,7 +41,16 @@ uint32_t G_wof_tables_main_mem_addr; uint32_t G_wof_tables_len; bool G_run_wof_main; +uint8_t G_sram_vfrt_ping_buffer[MIN_BCE_REQ_SIZE] __attribute__ ((section(".vfrt_ping_buffer"))); +uint8_t G_sram_vfrt_pong_buffer[MIN_BCE_REQ_SIZE] __attribute__ ((section(".vfrt_pong_buffer"))); wof_header_data_t G_wof_header __attribute__ ((section (".global_data"))); +uint32_t G_current_vfrt_addr = 0; + +//****************************************************************************** +// External Globals +//****************************************************************************** +extern GPE_BUFFER(ipcmsg_wof_vfrt_t G_wof_vfrt_parms); +extern GpeRequest G_wof_vfrt_req; @@ -152,3 +165,252 @@ uint8_t calc_quad_step_from_start( uint8_t i_num_active_quads ) return (G_wof_header.active_quads_size == ACTIVE_QUAD_SZ_MIN) ? 0 : (i_num_active_quads - 1); } + +/** + * calc_vfrt_address + * + * Description: Calculates the VFRT address based on the Ceff vdd/vdn and quad + * steps. + * + * Param[in]: i_vdd_step_from_start + * Param[in]: i_vdn_step_from_start + * Param[in]: i_quad_step_from_start + * + * Return: The desired VFRT address + */ +uint32_t calc_vfrt_mainstore_addr( uint16_t i_vdd_step_from_start, + uint16_t i_vdn_step_from_start, + uint8_t i_quad_step_from_start ) +{ + + // Wof tables address calculation + // (Base_addr + (sizeof VFRT * (total active quads * ( (i_vdn_step_from_start * vdd_size) + (i_vdd_step_from_start) ) + (i_quad_step_from_start)))) + uint32_t offset = G_wof_header.size_of_vfrt * + (( G_wof_header.active_quads_size * + ((i_vdn_step_from_start * G_wof_header.vdd_size) + + i_vdd_step_from_start) ) + i_quad_step_from_start); + + // Skip the wof header at the beginning of wof tables + uint32_t wof_tables_base = G_wof_tables_main_mem_addr + WOF_HEADER_SIZE; + + return wof_tables_base + offset; +} + + +/** + * copy_vfrt_to_sram + * + * Description: Call back function to copy VFRT into SRAM ping/pong buffer + * This call will also tell the PGPE that a new VFRT is available + * + * Param[in]: i_parms - pointer to a struct that will hold data necessary to + * the calculation. + * -Pointer to vfrt table temp buffer + * -Padding if the address needed to be 128-byte aligned + */ +void copy_vfrt_to_sram( copy_vfrt_to_sram_parms_t * i_parms) +{ +/* + * + * find out which ping pong buffer to use + * copy the vfrt to said ping pong buffer + * save current vfrt address to global + * send IPC command to pgpe to notify of new ping/pong vfrt address + */ + // Static variable to trac which buffer is open for use + // 0 = PING; 1 = PONG; + int l_gperc; // gpe schedule return code + static uint8_t L_pingpong = 0; + uint8_t * l_buffer_address; + + if( L_pingpong == 0 ) + { + // Use ping buffer + l_buffer_address = G_sram_vfrt_ping_buffer; + // Set next access to pong buffer + } + else + { + // Use pong buffer + l_buffer_address = G_sram_vfrt_pong_buffer; + // Set next access to ping buffer + } + + // Copy the vfrt data into the buffer + memcpy( l_buffer_address, + &(i_parms->vfrt_table->data[i_parms->pad]), + G_wof_header.size_of_vfrt ); + + // Set the parameters for the GpeRequest + G_wof_vfrt_parms.vfrt_ptr = l_buffer_address; + // TODO set this to Global amec field once we read shared sram + G_wof_vfrt_parms.active_quads = 1; + + // Send IPC command to PGPE with new vfrt address and active quads + // Should not need to check if request is idle as wof_main does before + // the WOF calculations begin. + l_gperc = gpe_request_schedule( &G_wof_vfrt_req ); + + // Confirm Successfull completion of WOF VFRT task + if(l_gperc != 0) + { + //Error in scheduling pgpe clip update task + TRAC_ERR("copy_vfrt_to_sram: Failed to schedule WOF VFRT task rc=%x", + l_gperc); + + /* @ + * @errortype + * @moduleid COPY_VFRT_TO_SRAM + * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE + * @userdata1 rc - gpe_request_schedule return code + * @userdata2 0 + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc OCC Failed to schedule a GPE job for clip update + */ + errlHndl_t l_errl = createErrl( + COPY_VFRT_TO_SRAM, // modId + GPE_REQUEST_SCHEDULE_FAILURE, // reasoncode + OCC_NO_EXTENDED_RC, // Extended reason code + ERRL_SEV_UNRECOVERABLE, // Severity + NULL, // Trace Buf + DEFAULT_TRACE_SIZE, // Trace Size + l_gperc, // userdata1 + 0 // userdata2 + ); + + // Callout firmware + addCalloutToErrl(l_errl, + ERRL_CALLOUT_TYPE_COMPONENT_ID, + ERRL_COMPONENT_ID_FIRMWARE, + ERRL_CALLOUT_PRIORITY_HIGH); + + // Commit error log + commitErrl(&l_errl); + } + else + { + // Sent the IPC command successfully, update which buffer we should look + // at next time. + L_pingpong = ~L_pingpong; + } + +} + + +/** + * send_vfrt_to_pgpe + * + * Description: Function to copy new VFRT from Mainstore to local SRAM buffer + * and calls copy_vfrt_to_sram callback function to send new VFRT + * to the PGPE + * Note: If desired VFRT is the same as previous, skip. + * + * Param[in]: i_vfrt_address - Address of the desired vfrt table. + */ +void send_vfrt_to_pgpe( uint32_t i_vfrt_address ) +{ + int l_ssxrc = SSX_OK; + uint32_t l_reasonCode = 0; + uint32_t l_extReasonCode = 0; + + do + { + if(i_vfrt_address == G_current_vfrt_addr) + { + // VFRT is unchanged. Skip + break; + } + else + { + // New VFRT needed from Mainstore, create BCE request to get it. + BceRequest l_vfrt_req; + + // 128-byte aligned temp buffer to hold data + temp_bce_request_buffer_t l_temp_bce_buff = {{0}}; + + + uint8_t l_pad = i_vfrt_address%128; + uint32_t l_vfrt_addr_128_aligned = i_vfrt_address - l_pad; + + // Create structure to hold parameters for callback function + copy_vfrt_to_sram_parms_t l_callback_parms; + l_callback_parms.vfrt_table = &l_temp_bce_buff; + l_callback_parms.pad = l_pad; + + + // Create request + l_ssxrc = bce_request_create( + &l_vfrt_req, // block copy object + &G_pba_bcde_queue, // main to sram copy engine + l_vfrt_addr_128_aligned, //mainstore address + (uint32_t) &l_temp_bce_buff, // SRAM start address + MIN_BCE_REQ_SIZE, // size of copy + SSX_WAIT_FOREVER, // no timeout + (AsyncRequestCallback)copy_vfrt_to_sram, + (void *)&l_callback_parms, + ASYNC_CALLBACK_IMMEDIATE ); + + if(l_ssxrc != SSX_OK) + { + CMDH_TRAC_ERR("read_wof_header: BCDE request create failure rc=[%08X]", -l_ssxrc); + /* + * @errortype + * @moduleid SEND_VFRT_TO_PGPE + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 RC for BCE block-copy engine + * @userdata2 Internal function checkpoint + * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE + * @devdesc Failed to create BCDE request + */ + l_reasonCode = SSX_GENERIC_FAILURE; + l_extReasonCode = ERC_BCE_REQUEST_CREATE_FAILURE; + break; + } + + // Do the actual copy + l_ssxrc = bce_request_schedule( &l_vfrt_req ); + + if(l_ssxrc != SSX_OK) + { + CMDH_TRAC_ERR("read_wof_header: BCE request schedule failure rc=[%08X]", -l_ssxrc); + /* + * @errortype + * @moduleid SEND_VFRT_TO_PGPE + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 RC for BCE block-copy engine + * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE + * @devdesc Failed to read PPMR data by using BCDE + */ + l_reasonCode = SSX_GENERIC_FAILURE; + l_extReasonCode = ERC_BCE_REQUEST_SCHEDULE_FAILURE; + break; + } + + } + }while( 0 ); + + // Check for errors and log, if any + if( l_ssxrc != SSX_OK ) + { + errlHndl_t l_errl = createErrl(SEND_VFRT_TO_PGPE, //modId + l_reasonCode, //reasoncode + l_extReasonCode, //Extended reason code + ERRL_SEV_UNRECOVERABLE, //Severity + NULL, //Trace Buf + 0, //Trace Size + -l_ssxrc, //userdata1 + 0); //userdata2 + + // Callout firmware + addCalloutToErrl(l_errl, + ERRL_CALLOUT_TYPE_COMPONENT_ID, + ERRL_COMPONENT_ID_FIRMWARE, + ERRL_CALLOUT_PRIORITY_HIGH); + + // Commit error log + commitErrl(&l_errl); + + return; + } + +} diff --git a/src/occ_405/wof/wof.h b/src/occ_405/wof/wof.h index 52a5ff0c..210e3cca 100644 --- a/src/occ_405/wof/wof.h +++ b/src/occ_405/wof/wof.h @@ -33,6 +33,8 @@ #define MIN_BCE_REQ_SIZE 256 #define ACTIVE_QUAD_SZ_MIN 1 #define ACTIVE_QUAD_SZ_MAX 6 +#define WOF_HEADER_SIZE 32 + typedef struct __attribute__ ((packed)) { @@ -50,7 +52,6 @@ typedef struct __attribute__ ((packed)) } wof_header_data_t; - typedef struct { // There is no guarantee that we can fit everything into the min BceRequest @@ -60,11 +61,17 @@ typedef struct uint8_t data[MIN_BCE_REQ_SIZE]; } temp_bce_request_buffer_t __attribute ((aligned(128))); +typedef struct +{ + temp_bce_request_buffer_t * vfrt_table; + uint8_t pad; +} copy_vfrt_to_sram_parms_t; + + //****************************************************************************** // Function Prototypes //****************************************************************************** - void wof_main( void ); uint16_t calculate_step_from_start( uint16_t i_ceff_vdx, @@ -76,4 +83,14 @@ uint8_t calc_quad_step_from_start( uint8_t i_num_active_quads ); +uint32_t calc_vfrt_mainstore_addr( uint16_t i_vdd_step_from_start, + uint16_t i_vdn_step_from_start, + uint8_t i_quad_step_from_start ); + +void copy_vfrt_to_sram( copy_vfrt_to_sram_parms_t * i_parms ); + +void send_vfrt_to_pgpe( uint32_t i_vfrt_address ); + + + #endif diff --git a/src/occ_405/wof/wof_service_codes.h b/src/occ_405/wof/wof_service_codes.h new file mode 100644 index 00000000..8967580e --- /dev/null +++ b/src/occ_405/wof/wof_service_codes.h @@ -0,0 +1,41 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/wof/wof_service_codes.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef _WOF_SERVICE_CODES_H_ +#define _WOF_SERVICE_CODES_H_ + +#include + +enum wofModuleId +{ + WOF_MAIN = WOF_COMP_ID | 0x01, + SEND_VFRT_TO_PGPE = WOF_COMP_ID | 0x02, + COPY_VFRT_TO_SRAM = WOF_COMP_ID | 0x03, +}; + + + + + +#endif /* #ifndef _WOF_SERVICE_CODES_H_ */