diff options
author | Mark Wenning <wenning@us.ibm.com> | 2012-07-17 15:02:16 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-07-30 19:10:30 -0500 |
commit | d3067d6f6e86e7ff1b795d9e67c9f298e18dfbbd (patch) | |
tree | a0fd7dfe901d0b06762b20746760629262191956 | |
parent | 0dbf0dfdd65a967045976979a33569db73fc0878 (diff) | |
download | talos-hostboot-d3067d6f6e86e7ff1b795d9e67c9f298e18dfbbd.tar.gz talos-hostboot-d3067d6f6e86e7ff1b795d9e67c9f298e18dfbbd.zip |
Implement proc_set_pore_bar HWP
Change-Id: I95562f9c3bb85e3b283020f62beaf65752281167
RTC: 42150
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1393
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
31 files changed, 4794 insertions, 617 deletions
diff --git a/src/include/usr/hwpf/istepreasoncodes.H b/src/include/usr/hwpf/istepreasoncodes.H index c186e1e87..084f633ae 100644 --- a/src/include/usr/hwpf/istepreasoncodes.H +++ b/src/include/usr/hwpf/istepreasoncodes.H @@ -51,6 +51,8 @@ enum istepModuleId ISTEP_START_PAYLOAD_CALL_SHUTDOWN = 0x02, ISTEP_START_PAYLOAD_NOTIFY_FSP = 0x03, ISTEP_ACTIVATE_SLAVE_CORES = 0x04, + ISTEP_BUILD_WINKLE_IMAGES = 0x05, + ISTEP_CORE_ACTIVATE = 0x06, }; /** @@ -66,6 +68,7 @@ enum istepReasonCode ISTEP_TARGET_NULL = ISTEP_COMP_ID | 0x02, ISTEP_MBOX_MSG_NULL = ISTEP_COMP_ID | 0x03, ISTEP_BAD_RC = ISTEP_COMP_ID | 0x04, + ISTEP_FAIL_MASTER_WINKLE_RC = ISTEP_COMP_ID | 0x05, }; }; // end ISTEP diff --git a/src/include/usr/targeting/common/utilFilter.H b/src/include/usr/targeting/common/utilFilter.H index 9b58b2fdb..b33afa6f6 100644 --- a/src/include/usr/targeting/common/utilFilter.H +++ b/src/include/usr/targeting/common/utilFilter.H @@ -131,6 +131,14 @@ void getAllLogicalCards( TARGETING::TargetHandleList & o_vector, TYPE i_cardType, bool i_functional = true ); + +/** + * @brief find master core in system + * + * @return master target core, NULL otherwise + */ +const TARGETING::Target * getMasterCore( ); + } #endif // __TARGETING_COMMON_UTIL_H diff --git a/src/include/usr/vmmconst.h b/src/include/usr/vmmconst.h index ee531ca86..9c569289d 100644 --- a/src/include/usr/vmmconst.h +++ b/src/include/usr/vmmconst.h @@ -89,9 +89,10 @@ enum BlockPriority /** Page Size in bits per SLBE */ #define SLBE_b 12 -/** Hardwired pointer to output PORE image, temporary location */ +/** Hardwired pointer to output SLW image, temporary location */ +/** SLW image must be on 1M boundary */ /** MAX image size is 512 K */ -#define OUTPUT_PORE_IMG_ADDR 0x780000 +#define OUTPUT_PORE_IMG_ADDR 0x400000 #define MAX_OUTPUT_PORE_IMG_SIZE 512*1024 diff --git a/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C b/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C index e2ad1fec6..afabde42a 100644 --- a/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C +++ b/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C @@ -34,6 +34,7 @@ /******************************************************************************/ #include <stdint.h> +#include <sys/misc.h> // cpu_thread_count() #include <vfs/vfs.H> // PORE image #include <trace/interface.H> @@ -59,7 +60,7 @@ // Uncomment these files as they become available: #include "proc_slw_build/proc_slw_build.H" -// #include "proc_set_pore_bar/proc_set_pore_bar.H" +#include "proc_set_pore_bar/proc_set_pore_bar.H" namespace BUILD_WINKLE_IMAGES { @@ -73,11 +74,9 @@ using namespace DeviceFW; /** * @def pointer to area for output PORE image * @todo - make system call to allocate 512k - 1M of space to put output - * image. Currently hardwired to 0x78000 - * + * image for the master chip. + * Currently hardwired to 0x400000 */ -void * const g_pOutputPoreImg - = reinterpret_cast<void * const >(OUTPUT_PORE_IMG_ADDR); /** * @brief Load PORE image and return a pointer to it, or NULL @@ -94,9 +93,9 @@ void * const g_pOutputPoreImg * HWP's are finished. * */ -errlHndl_t loadPoreImage( TARGETING::Target *i_CpuTarget, - const char *& o_rporeAddr, - size_t & o_rporeSize ) +errlHndl_t loadPoreImage( const TARGETING::Target *i_CpuTarget, + const char *& o_rporeAddr, + size_t & o_rporeSize ) { errlHndl_t l_errl = NULL; const char * fileName = "procpore.dat"; @@ -152,6 +151,144 @@ errlHndl_t loadPoreImage( TARGETING::Target *i_CpuTarget, return l_errl; } + +/** + * @brief apply cpu reg information to the SLW image using + * p8_pore_gen_cpureg() . + * + * @param io_image - pointer to the SLW image + * @param i_sizeImage - size of the SLW image + * + * @return errorlog if error, NULL otherwise. + * + * @todo $$ pore_gen_cpu_reg not supported this sprint (???), leave main code + * commented out for now. + * @todo $$ l_regname is defined as "unswizzled spr value" ???? + */ +errlHndl_t applyPoreGenCpuRegs( TARGETING::Target *i_cpuTarget, + void *io_image, + uint32_t i_sizeImage ) +{ + errlHndl_t l_errl = NULL; + + TARGETING::TargetHandleList l_coreIds; + getChildChiplets( l_coreIds, + i_cpuTarget, + TYPE_CORE, + true ); + + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "applyPoreGenCpuRegs: Process cores=0x%x, threads=0x%x", + l_coreIds.size(), + cpu_thread_count() ); + +#if 1 + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "applyPoreGenCpuRegs: DISABLED until pore_gen_cpureg integration" ); + + // $$ this will be turned on when we integrate pore_gen_cpureg + // $$ @todo RTC 41425 +#else + size_t l_threadid = 0; + size_t l_coreid = 0; + uint32_t l_rc = 0; + uint64_t l_msrcVal = cpu_spr_value(CPU_SPR_MSRC) ; + uint64_t l_lpcrVal = cpu_spr_value(CPU_SPR_LPCR) ; + uint64_t l_hrmorVal = cpu_spr_value(CPU_SPR_HRMOR); + for ( l_coreid=0; l_coreid < l_coreIds.size(); l_coreid++ ) + { + for ( l_threadid=0; l_threadid < cpu_thread_count(); l_threadid++ ) + { + + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "core=0x%x,thread=0x%x: ", + l_coreid, + l_threadid ); + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "msrc=0x%x,lpcr=0x%x,hrmor=0x%x", + l_msrcVal, + l_lpcrVal, + l_hrmorVal ); + do { + l_rc = p8_pore_gen_cpureg( io_image, + i_sizeImage, + l_regName, + l_msrcVal, + l_coreid, + l_threadid); + if ( l_rc ) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "p8_pore_gen_cpu_reg ERROR: MSRC: core=0x%x,thread=0x%x,l_rc=0x%x", + l_coreId, + l_threadId, + l_rc ); + break; + } + + l_rc = p8_pore_gen_cpureg( io_image, + i_sizeImage, + l_regName, + l_lpcrVal, + l_coreid, + l_threadid); + if ( l_rc ) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "p8_pore_gen_cpu_reg ERROR: LPCR: core=0x%x,thread=0x%x,l_rc=0x%x", + l_coreId, + l_threadId, + l_rc ); + break; + } + + l_rc = p8_pore_gen_cpureg( io_image, + i_sizeImage, + l_regName, + l_hrmorVal, + l_coreid, + l_threadid); + if ( l_rc ){ + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "p8_pore_gen_cpu_reg ERROR: HRMOR: core=0x%x,thread=0x%x,l_rc=0x%x", + l_coreId, + l_threadId, + l_rc ); + break; + } + + + } while (0); + + if ( l_rc ){ + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "p8_pore_gen_cpu_reg ERROR: core=0x%x, thread=0x%x, l_rc=0x%x", + l_coreId, + l_threadId, + l_rc ); + /*@ + * @errortype + * @reasoncode ISTEP_BAD_RC + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid ISTEP_BUILD_WINKLE_IMAGES + * @userdata1 return code from p8_pore_gen_cpureg + * + * @devdesc p8_pore_gen_cpureg returned an error when + * attempting to change a reg value in the PORE image. + */ + l_errl = + new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + ISTEP_BUILD_WINKLE_IMAGES, + ISTEP_BAD_RC, + l_rc ); + } + } // end for l_threadId + } // end for l_coreId +#endif + + return l_errl; +} + // // Wrapper function to call 15.1 : // host_build_winkle @@ -159,40 +296,33 @@ errlHndl_t loadPoreImage( TARGETING::Target *i_CpuTarget, void call_host_build_winkle( void *io_pArgs ) { errlHndl_t l_errl = NULL; - uint8_t l_cpuNum = 0; const char *l_pPoreImage = NULL; size_t l_poreSize = 0; void *l_pImageOut = NULL; uint32_t l_sizeImageOut = MAX_OUTPUT_PORE_IMG_SIZE; - TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_build_winkle entry" ); // @@@@@ CUSTOM BLOCK: @@@@@ - // figure out what targets we need - // customize any other inputs - // set up loops to go through all targets (if parallel, spin off a task) - + // find the master core, i.e. the one we are running on + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Find master chip: " ); - TARGETING::TargetHandleList l_cpuTargetList; - getAllChips(l_cpuTargetList, TYPE_PROC); + const TARGETING::Target* l_masterCore = getMasterCore( ); + assert( l_masterCore != NULL ); - for ( l_cpuNum=0; l_cpuNum < l_cpuTargetList.size(); l_cpuNum++ ) - { - // make a local copy of the CPU target - TARGETING::Target* l_cpu_target = l_cpuTargetList[l_cpuNum]; + TARGETING::Target* l_cpu_target = const_cast<TARGETING::Target *> + ( getParentChip( l_masterCore ) ); - TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, - "Run cpuNum 0x%x", - l_cpuNum ); + // dump physical path to target + EntityPath l_path; + l_path = l_cpu_target->getAttr<ATTR_PHYS_PATH>(); + l_path.dump(); - // dump physical path to target - EntityPath l_path; - l_path = l_cpu_target->getAttr<ATTR_PHYS_PATH>(); - l_path.dump(); + do { l_errl = loadPoreImage( l_cpu_target, l_pPoreImage, @@ -205,20 +335,29 @@ void call_host_build_winkle( void *io_pArgs ) // drop out of loop and return errlog to fail. break; } - - // cast OUR type of target to a FAPI type of target. - const fapi::Target l_fapi_cpu_target( - TARGET_TYPE_PROC_CHIP, - reinterpret_cast<void *> - (const_cast<TARGETING::Target*>(l_cpu_target)) ); - // - // stub - get address of output buffer for PORE image for this CPU, - // and load it there + // @todo stub - eventually this will make a system call to get storage + // ( and size ) for the output buffer for PORE image for this CPU. + // Save the results in attributes so that other isteps/substeps can + // use it. // - l_pImageOut = g_pOutputPoreImg; + // @NOTE NOTE NOTE + // This address must be on a 1-meg boundary. + // + l_pImageOut = reinterpret_cast<void * const >(OUTPUT_PORE_IMG_ADDR); + l_cpu_target->setAttr<TARGETING::ATTR_SLW_IMAGE_ADDR> + ( OUTPUT_PORE_IMG_ADDR ); + l_sizeImageOut = MAX_OUTPUT_PORE_IMG_SIZE; + l_cpu_target->setAttr<TARGETING::ATTR_SLW_IMAGE_SIZE> + ( MAX_OUTPUT_PORE_IMG_SIZE ); + // cast OUR type of target to a FAPI type of target. + const fapi::Target l_fapi_cpu_target( + TARGET_TYPE_PROC_CHIP, + reinterpret_cast<void *> + (const_cast<TARGETING::Target*> + (l_cpu_target)) ); // call the HWP with each fapi::Target FAPI_INVOKE_HWP( l_errl, @@ -244,7 +383,25 @@ void call_host_build_winkle( void *io_pArgs ) l_sizeImageOut ); } - } // endfor + // set the actual size of the image now. + l_cpu_target->setAttr<TARGETING::ATTR_SLW_IMAGE_SIZE> + ( l_sizeImageOut ); + + // apply the cpu reg information to the image. + l_errl = applyPoreGenCpuRegs( l_cpu_target, + l_pImageOut, + l_sizeImageOut ); + if ( l_errl ) + { + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, + "applyPoreGenCpuRegs ERROR : Returning errorlog, PLID=0x%x", + l_errl->plid() ); + // drop out if we hit an error and quit. + break; + } + + } while (0); // end do block + // @@@@@ END CUSTOM BLOCK: @@@@@ @@ -263,43 +420,96 @@ void call_host_build_winkle( void *io_pArgs ) // void call_proc_set_pore_bar( void *io_pArgs ) { - errlHndl_t l_errl = NULL; + errlHndl_t l_errl = NULL; TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_proc_set_pore_bar entry" ); -#if 0 // @@@@@ CUSTOM BLOCK: @@@@@ - // figure out what targets we need - // customize any other inputs - // set up loops to go through all targets (if parallel, spin off a task) - // dump physical path to targets + const TARGETING::Target* l_masterCore = TARGETING::getMasterCore( ); + assert( l_masterCore != NULL ); + + TARGETING::Target* l_cpu_target = const_cast<TARGETING::Target *> + ( getParentChip( l_masterCore ) ); + + // dump physical path to target EntityPath l_path; - l_path = l_@targetN_target->getAttr<ATTR_PHYS_PATH>(); + l_path = l_cpu_target->getAttr<ATTR_PHYS_PATH>(); l_path.dump(); - // cast OUR type of target to a FAPI type of target. - const fapi::Target l_fapi_@targetN_target( - TARGET_TYPE_MEMBUF_CHIP, - reinterpret_cast<void *> - (const_cast<TARGETING::Target*>(l_@targetN_target)) ); + do { - // call the HWP with each fapi::Target - FAPI_INVOKE_HWP( l_errl, proc_set_pore_bar, _args_...); - if ( l_errl ) - { - TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, - "ERROR : .........." ); - errlCommit( l_errl, HWPF_COMP_ID ); - } - else - { + // fetch image location and size, written by host_build_winkle above + + // Note that the "i_mem_bar" input to proc_set_pore_bar is the physical + // address of the PORE image, this is the image that will get executed + // at winkle. The void * i_image parameter actually points to the same + // place in HostBoot; in fsp or cronus these will be different. + // + // @todo this may change for secure boot, need to make up an RTC + // to handle this, or there may one already??? + // + uint64_t l_imageAddr = + l_cpu_target->getAttr<TARGETING::ATTR_SLW_IMAGE_ADDR>(); + + + // $$ @todo the hardware wants a mask to cover the size of the image, + // with the added proviso that the lower 5 nybbles of the mask must + // always be 0. + // Thus, as long as the image is under 1M, this value will be 0 . + // The HWP guys will probably pull this calculation inside + // proc_set_pore_bar() so that we just specify the size in bytes. + // This comment will be left until we integrate the new version. + // In the meantime, l_mem_mask should be set to 0 to work correctly. + uint64_t l_mem_mask = 0; + + // defined in proc_set_pore_bar.H + uint32_t l_mem_type = SLW_L3 ; + + // cast OUR type of target to a FAPI type of target. + const fapi::Target l_fapi_cpu_target( + TARGET_TYPE_PROC_CHIP, + reinterpret_cast<void *> + (const_cast<TARGETING::Target*> + (l_cpu_target)) ); + + // call the HWP with each fapi::Target TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, - "SUCCESS : .........." ); - } + "Call proc_set_pore_bar, membar=0x%lx, size=0x%lx, mask=0x%lx, type=0x%x", + l_imageAddr, + (l_cpu_target->getAttr<ATTR_SLW_IMAGE_SIZE>()), + l_mem_mask, + l_mem_type ); + + + void * const l_pImage = reinterpret_cast<void * const>(l_imageAddr); + + FAPI_INVOKE_HWP( l_errl, + proc_set_pore_bar, + l_fapi_cpu_target, + l_pImage, + l_imageAddr, + l_mem_mask, + l_mem_type + ); + + if ( l_errl ) + { + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, + "ERROR : proc_set_pore_bar, PLID=0x%x", + l_errl->plid() ); + } + else + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "SUCCESS : proc_set_pore_bar" ); + } + + } while ( 0 ); // end do block + // @@@@@ END CUSTOM BLOCK: @@@@@ -#endif + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_proc_set_pore_bar exit" ); diff --git a/src/usr/hwpf/hwp/build_winkle_images/makefile b/src/usr/hwpf/hwp/build_winkle_images/makefile index c970dfd84..815db6200 100644 --- a/src/usr/hwpf/hwp/build_winkle_images/makefile +++ b/src/usr/hwpf/hwp/build_winkle_images/makefile @@ -41,6 +41,9 @@ EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images ## EXAMPLE: ## EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/<HWP_dir> EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/pore_gen_cpureg CUSTOMFLAGS+= -D __FAPI @@ -52,15 +55,20 @@ OBJS = build_winkle_images.o \ p8_scan_compression.o \ pore_inline_assembler.o \ proc_slw_build.o \ - sbe_xip_image.o + sbe_xip_image.o \ + proc_set_pore_bar.o \ + proc_pba_bar_config.o ## NOTE: add a new directory onto the vpaths when you add a new HWP ## EXAMPLE: # VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/<HWP_dir> VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build +VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar +VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config +VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/pore_gen_cpureg ## Point to the PORE image in PNOR -BINARY_FILES = $(IMGDIR)/procpore.dat:1f6e49c91e2a2b0df5fad6c215c8f09d9f19fce6 +BINARY_FILES = $(IMGDIR)/procpore.dat:72cc5bef88f4d55dd9bbc9ad096e7dacff7d46e4 include ${ROOTPATH}/config.mk diff --git a/src/usr/hwpf/hwp/build_winkle_images/pore_gen_cpureg/HvPlicModule.H b/src/usr/hwpf/hwp/build_winkle_images/pore_gen_cpureg/HvPlicModule.H new file mode 100644 index 000000000..859c217cd --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/pore_gen_cpureg/HvPlicModule.H @@ -0,0 +1,24 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/hwpf/hwp/build_winkle_images/pore_gen_cpureg/HvPlicModule.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ + diff --git a/src/usr/hwpf/hwp/build_winkle_images/pore_gen_cpureg/p8_pore_table_gen_api.H b/src/usr/hwpf/hwp/build_winkle_images/pore_gen_cpureg/p8_pore_table_gen_api.H new file mode 100644 index 000000000..e78a31e7a --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/pore_gen_cpureg/p8_pore_table_gen_api.H @@ -0,0 +1,286 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/hwpf/hwp/build_winkle_images/pore_gen_cpureg/p8_pore_table_gen_api.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +/*------------------------------------------------------------------------------*/ +/* *! (C) Copyright International Business Machines Corp. 2012 */ +/* *! All Rights Reserved -- Property of IBM */ +/* *! *** IBM Confidential *** */ +/*------------------------------------------------------------------------------*/ +/* *! TITLE : p8_pore_table_gen_api */ +/* *! DESCRIPTION : Contains all external APIs used by firmware (PHYP) to */ +// generate/modify the P8 PORE SLW image with /Ramming and +// Scomming specific instructions to be executed on exit from +// Sleep/Winkle. Also contains definitions for the ramming +// PORE code. +/* *! OWNER NAME : Michael Olsen Email: cmolsen@us.ibm.com */ +// +/* *! COMMENTS : *** VERY IMPORTANT *** */ +// The "Shared RAM section", the "Pore RAM section" and the +// "C-code RAM section" must closely match eachother. +// +/*------------------------------------------------------------------------------*/ + +#ifndef _P8_PORE_TABLE_GEN_API_H +#define _P8_PORE_TABLE_GEN_API_H + +/********************************************************************/ +/* Shared RAM section - begin */ +/* This section MUST perfectly match the "Pore/C-code RAM section". */ +/********************************************************************/ +// Header defs (P8&PORE 64-bit notation where bits are numbered from left-to-right). +// (Some of these defs are used in the c-specific section further down.) +// ----------------------------------------------------------------------------- +// Note: SPR register numbers have a swizzle about them per PPC architecture +// spr(instruction) <- spr5:9 || spr0:4 +// +// For the PGAS routine, it is assumed that the API does the swizzling upon +// building the instruction held in this structure +// +// Header configuration: CPU Register Operation Header +// 0 - End: 1=End; 0=More +// 1 - Reserved +// 2:3 - Type +// 00: MTSPR +// 01: MTGPR +// 10: Reserved +// 11: Reserved +// 4:13 - SPR number in non-swizzled form (0:9) +// 14:15 - Reserved for SPR nunmber expansion +// 16:18 - Thread ID +// 19:31 - Reserved + +#define RAM_HEADER_END_START 0 +#define RAM_HEADER_END_MASK BITS(RAM_HEADER_END_START,1) +#define RAM_HEADER_TYPE_START 2 +#define RAM_HEADER_TYPE_MASK BITS(RAM_HEADER_TYPE_START,2) +#define RAM_HEADER_SPRN_START 4 +#define RAM_HEADER_SPRN_MASK BITS(RAM_HEADER_SPRN_START,10) +#define RAM_HEADER_THREAD_START 16 +#define RAM_HEADER_THREAD_MASK BITS(RAM_HEADER_THREAD_START,3) +#define RAM_INSTR_START 32 +#define RAM_INSTR_MASK BITS(RAM_INSTR_START,32) +// MTSPR instr defs +#define RAM_MTSPR_INSTR_TEMPL ( ( (uint64_t)31<<(63-5) | (uint64_t)467<<(63-30) ) ) +#define RAM_MTSPR_SPR_START 11 +#define RAM_MTSPR_SPR_MASK BITS(RAM_MTSPR_SPR_START,10) +// Thread align defs +#define RAM_HEADER_THREAD_RALIGN ( 61-16 ) // 3 Bit shift right amount +#define RAM_HEADER_THREAD_LALIGN ( 61-16 ) // 3 Bit shift left amount +/********************************************************************/ +/* Shared RAM section - end */ +/********************************************************************/ + + +#ifdef FOR_PORE_RAMMING + +// Thread status +CONST_UINT64_T( PROC_RAS_STAT_10013002 , ULL(0x10013002) ); + +// TCTL RAS Status (for each thread) +// Note: the address is not included in the name to ease PGAS indexing +// of these registers +CONST_UINT64_T( EX_PERV_TCTL0_R_STAT , ULL(0x10013002) ); +CONST_UINT64_T( EX_PERV_TCTL1_R_STAT , ULL(0x10013012) ); +CONST_UINT64_T( EX_PERV_TCTL2_R_STAT , ULL(0x10013022) ); +CONST_UINT64_T( EX_PERV_TCTL3_R_STAT , ULL(0x10013032) ); +CONST_UINT64_T( EX_PERV_TCTL4_R_STAT , ULL(0x10013042) ); +CONST_UINT64_T( EX_PERV_TCTL5_R_STAT , ULL(0x10013052) ); +CONST_UINT64_T( EX_PERV_TCTL6_R_STAT , ULL(0x10013062) ); +CONST_UINT64_T( EX_PERV_TCTL7_R_STAT , ULL(0x10013072) ); + +// Thread scratch registers +// Note: the address is not included in the name to ease PGAS indexing +// of these registers +CONST_UINT64_T( EX_PERV_SCRATCH0 , ULL(0x10013283) ); +CONST_UINT64_T( EX_PERV_SCRATCH1 , ULL(0x10013284) ); +CONST_UINT64_T( EX_PERV_SCRATCH2 , ULL(0x10013285) ); +CONST_UINT64_T( EX_PERV_SCRATCH3 , ULL(0x10013286) ); +CONST_UINT64_T( EX_PERV_SCRATCH4 , ULL(0x10013287) ); +CONST_UINT64_T( EX_PERV_SCRATCH5 , ULL(0x10013288) ); +CONST_UINT64_T( EX_PERV_SCRATCH6 , ULL(0x10013289) ); +CONST_UINT64_T( EX_PERV_SCRATCH7 , ULL(0x1001328A) ); + +// Max # of polling attempts. SLW ops have no quiescent needs, so low #. +CONST_UINT32_T( SLW_MAX_RAM_POLLS , ULL(0x04) ); + +// mfspr gpr0, scratch0 opcode left-shifted 29 bits, ready for ramming. +CONST_UINT64_T( MFSPR_GPR0_SCRATCH0_RAM_READY, (0x000000007C1542A6<<29)); + +#ifdef __ASSEMBLER__ + +/***********************************************************************/ +/* Pore RAM section - begin */ +/* This section MUST perfectly match the "Shared/C-code RAM section". */ +/***********************************************************************/ +.set RAM_HEADER, 0 +.set RAM_INSTR, 4 +.set RAM_DATA, 8 +.set RAM_ENTRY_LENGTH, 16 +/***********************************************************************/ +/* Pore RAM section - end */ +/***********************************************************************/ + +#endif // __ASSEMBLER__ + + +#else // Not FOR_PORE_RAMMING + + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> + +#include "pore_bitmanip.H" + +// Header defs (C notation where bits are numbered from right-to-left, and reducing to 32-bit) +#define RAM_HEADER_END_START_C ( 31-RAM_HEADER_END_START+1-1 ) +#define RAM_HEADER_END_MASK_C (uint32_t)(RAM_HEADER_END_MASK>>32) +#define RAM_HEADER_TYPE_START_C ( 31-RAM_HEADER_TYPE_START+1-2 ) +#define RAM_HEADER_TYPE_MASK_C (uint32_t)(RAM_HEADER_TYPE_MASK>>32) +#define RAM_HEADER_SPRN_START_C ( 31-RAM_HEADER_SPRN_START+1-10 ) +#define RAM_HEADER_SPRN_MASK_C (uint32_t)(RAM_HEADER_SPRN_MASK>>32) +#define RAM_HEADER_THREAD_START_C ( 31-RAM_HEADER_THREAD_START+1-3 ) +#define RAM_HEADER_THREAD_MASK_C (uint32_t)(RAM_HEADER_THREAD_MASK>>32) +// MTSPR instr defs +#define RAM_MTSPR_INSTR_TEMPL_C ( ( (uint32_t)31<<(31-5) | (uint32_t)467<<(31-30) ) ) +#define RAM_MTSPR_SPR_START_C ( 31-RAM_MTSPR_SPR_START+1-10 ) +//#define RAM_MTSPR_SPR_MASK_C (uint32_t)(BITS(RAM_MTSPR_SPR_START,10)>>32) +#define RAM_MTSPR_SPR_MASK_C (uint32_t)(RAM_MTSPR_SPR_MASK>>32) + +/* Other defs needed for ramming */ +// TOC names +#define SLW_HOST_REG_VECTOR_TOC_NAME "slw_host_reg_vector" +#define SLW_HOST_SCOM_VECTOR_TOC_NAME "slw_host_scom_vector" +#define SLW_HOST_REG_TABLE_TOC_NAME "slw_core_reg_table" + +// Defines for slw_build() to update "host_runtime_scom" w/pointer to "sub_slw_runtime_scom" at SLW image build time. +#define HOST_RUNTIME_SCOM_TOC_NAME "host_runtime_scom" // Null 1st, then fill w/addr of SLW_RUNTIME_SCOM_TOC_NAME +#define SLW_RUNTIME_SCOM_TOC_NAME "sub_slw_runtime_scom" + +// RAM table defines +#define XIPSIZE_RAM_ENTRY ( (sizeof(RamTableEntry)+7)/8*8 ) +#define SLW_MAX_CORES 16 +#define SLW_MAX_CPUREGS_CORE 8 +#define SLW_MAX_CPUREGS_THREADS 2 // Was 3 at some point, when MSR reg was included? +#define SLW_CORE_THREADS 8 +#define SLW_MAX_CPUREGS_OPS ( SLW_MAX_CPUREGS_CORE + \ + SLW_CORE_THREADS*SLW_MAX_CPUREGS_THREADS ) +// $$ mww 2012-07-19 SLW_SLW_SECTION_SIZE removed? needed by proc_slw_build +#define SLW_SLW_SECTION_SIZE ( SLW_MAX_CORES * SLW_MAX_CPUREGS_OPS * XIPSIZE_RAM_ENTRY ) +#define SLW_RAM_TABLE_SIZE ( SLW_MAX_CORES * SLW_MAX_CPUREGS_OPS * XIPSIZE_RAM_ENTRY ) + +// SCOM table defines +#define XIPSIZE_SCOM_ENTRY 16 +#define SLW_MAX_SCOMS 32 +#define SLW_SCOM_TABLE_SPACE_PER_CORE ( (SLW_MAX_SCOMS+1)*XIPSIZE_SCOM_ENTRY ) // Add 1 for RNNN IIS +#define SLW_SCOM_TABLE_SIZE ( SLW_MAX_CORES * SLW_SCOM_TABLE_SPACE_PER_CORE ) + +// SCOM/CID masks and ranges +#define P8_CID_EX_LOW 0x10 // Lowest EX chiplet addr +#define P8_CID_EX_HIGH 0x1f // Highest EX chiplet addr + +// SCOM Operators +#define P8_PORE_SCOM_FIRST_OP 1 // First supported INPUT Scom operation. +#define P8_PORE_SCOM_APPEND 0 // Add Scom to the end of table (only used internally) +#define P8_PORE_SCOM_REPLACE 1 // Replace existing Scom, or append to end of table +#define P8_PORE_SCOM_OR 2 // Overlay data onto existing Scom by bitwise OR +#define P8_PORE_SCOM_AND 3 // Overlay data onto existing Scom by bitwise AND +#define P8_PORE_SCOM_NOOP 4 // Replace existing Scom PORE NOP instruction +#define P8_PORE_SCOM_RESET 5 // Delete all entries for given coreID. Repl w/RNNN IIS +#define P8_PORE_SCOM_LAST_OP 5 // Keep track of the last op for checking correctness of op input + + +// Return codes +#define SLW_RAM_SUCCESS 0 +#define SLW_RAM_HEADERS_NOT_SYNCED 1 +#define SLW_RAM_IMAGE_SIZE_MISMATCH 2 +#define SLW_RAM_TABLE_ENTRY_OVERFLOW 3 +#define SLW_RAM_CODE_ERROR 4 +#define SLW_RAM_INVALID_PARAMETER 5 +#define SLW_RAM_WARNING_TABLE_CONTAMINATION 6 + + +#ifdef __cpluscplus +extern "C" { +#endif + +/********************************************************************/ +/* C-code RAM section - begin */ +/* This section MUST perfectly match the "Shared/Pore RAM section". */ +/********************************************************************/ +typedef struct ram_instr_t { + uint32_t header; + uint32_t instr; + uint64_t data; +} RamTableEntry; +/********************************************************************/ +/* C-code RAM section - end */ +/********************************************************************/ + +// SLW supported SPR registers +typedef struct { + const char *name; + uint32_t value; + uint32_t swizzled; +} SlwSprRegs; + + +/* Name: p8_pore_gen_cpureg() + * Description: Populates ramming entries in the .slw section + * Parameter list: i_image - pointer to SLW mainstore image + * i_sizeImage - size of SLW mainstore image + * i_regName - unswizzled SPR register value + * i_regData - data to write to SPR register + * i_coreId - the core ID to operate on + * i_threadId - the thread ID to operate on + */ +uint32_t p8_pore_gen_cpureg(void *io_image, + uint32_t i_sizeImage, + uint32_t i_regName, + uint64_t i_regData, + uint32_t i_coreId, + uint32_t i_threadId); + +/* Name: p8_pore_gen_scom() + * Description: Populates scom entries in the .slw section + * Parameter list: i_image - pointer to SLW mainstore image + * i_sizeImage - size of SLW mainstore image + * i_scomAddr - scom register address + * i_scomData - 64-bit data to put in scom register + * i_operation - what to do with the scom data + * i_coreId - the core ID [0:15] + */ +uint32_t p8_pore_gen_scom(void *io_image, + uint32_t i_sizeImage, + uint32_t i_scomAddr, + uint32_t i_coreId, + uint64_t i_scomData, + uint32_t i_operation); + +#ifdef __cpluscplus +} +#endif + +#endif // FOR_PORE_RAMMING + +#endif // _P8_PORE_TABLE_GEN_API_H diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config.C b/src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config.C new file mode 100644 index 000000000..72eff97b2 --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config.C @@ -0,0 +1,254 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config.C $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +// $Id: proc_pba_bar_config.C,v 1.6 2012/05/23 15:22:10 stillgs Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/proc_pba_bar_config.C,v $ +//------------------------------------------------------------------------------ +// *! (C) Copyright International Business Machines Corp. 2011 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//------------------------------------------------------------------------------ +// *! OWNER NAME: Klaus P. Gungl Email: kgungl@de.ibm.com +// *! +// *! +/// \file proc_pba_bar_config.C +/// \brief Initialize PAB and PAB_MSK of PBA +// *! +// *! The purpose of this procedure is to set the PBA BAR, PBA BAR Mask and PBA scope value / registers +// *! +// *! Following proposals here: pass values for one set of pbabar, pass reference to structure for one set of pbabar, pass struct of struct containing +// *! all setup values +// *! +// *! High-level procedure flow: +// *! parameter checking +// *! set PBA_BAR +// *! set PBA_BARMSK +// *! +// *! Procedure Prereq: +// *! o System clocks are running +// *! +// *! list of changes +// *! 2011/11/22 all variables / passing calling parameters are uint64_t, cmd_scope is enum, MASK is not bitmask parameter but size +// *! structure for init contain uint64_t only. +// *! +//------------------------------------------------------------------------------ + + +// ---------------------------------------------------------------------- +// Includes +// ---------------------------------------------------------------------- +#include <fapi.H> +#include "p8_scom_addresses.H" +#include "proc_pba_init.H" +#include "proc_pba_bar_config.H" +#include "proc_pm.H" + + +extern "C" { + + +using namespace fapi; + +// ---------------------------------------------------------------------- +// Constant definitions +// ---------------------------------------------------------------------- + +// for range checking 0x0123456701234567 +#define BAR_ADDR_RANGECHECK_ 0x0003FFFFFFF00000ull +#define BAR_ADDR_RANGECHECK_HIGH 0xFFFC000000000000ull +#define BAR_ADDR_RANGECHECK_LOW 0x00000000000FFFFFull +#define BAR_MASK_RANGECHECK 0x000001FFFFF00000ull +#define BAR_MASK_RANGECHECK_HIGH 0xFFFFFE0000000000ull +#define BAR_MASK_RANGECHECK_LOW 0x00000000000FFFFFull + +// ---------------------------------------------------------------------- +// Global variables +// ---------------------------------------------------------------------- + +// ---------------------------------------------------------------------- +// Prototypes +// ---------------------------------------------------------------------- + +// ---------------------------------------------------------------------- +// Function definitions +// ---------------------------------------------------------------------- + +// --------------------------------------------- proc_pba_bar_config ---- +// function: +// initialize initialize a specific set of PBA_BAR (=cmd_scope and address), PBA_BARMSK (mask/size) +// pass values directly +//! init_pba_bar_ps +//! initialize a set of PBA_BAR and PBA_BARMSK registers, calling parameters: reference to structure of initialization values +/*! +@param i_target the target +@param i_index specifies which set of BAR / BARMSK registers to set. [0..3] +@param i_pba_bar_addr PBA base address - 1MB grandularity +@param i_pba_bar_mask PBA base address mask that defines the bits that are not used from the PBA base address - 1MB grandularity + The value of this mask + 1 defines the size of the window that is accessible. + (ex. 700000 yields an 8MB region) +@param i_pba_cmd_scope command scope according to pba spec +*/ + +fapi::ReturnCode +proc_pba_bar_config (const Target& i_target, + uint32_t i_index, + uint64_t i_pba_bar_addr, + uint64_t i_pba_bar_mask, + uint64_t i_pba_cmd_scope + ) +{ + + // Define structures that map the register fields + + typedef union pba_barn { + uint64_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t high_order; + uint32_t low_order; +#else + uint32_t low_order; + uint32_t high_order; +#endif // _BIG_ENDIAN + } words; + struct { +#ifdef _BIG_ENDIAN + uint64_t cmd_scope : 3; + uint64_t reserved0 : 1; + uint64_t reserved1 : 10; + uint64_t addr : 50; +#else + uint64_t addr : 50; + uint64_t reserved1 : 10; + uint64_t reserved0 : 1; + uint64_t cmd_scope : 3; +#endif // _BIG_ENDIAN + } fields; + } pba_barn_t; + + + typedef union pba_barmskn { + uint64_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t high_order; + uint32_t low_order; +#else + uint32_t low_order; + uint32_t high_order; +#endif // _BIG_ENDIAN + } words; + struct { +#ifdef _BIG_ENDIAN + uint64_t reserved0 : 23; + uint64_t mask : 41; +#else + uint64_t mask : 41; + uint64_t reserved0 : 23; +#endif // _BIG_ENDIAN + } fields; + } pba_barmskn_t; + + + + ecmdDataBufferBase data(64); + fapi::ReturnCode l_rc; + uint32_t l_ecmdRc = 0; + + pba_barn_t bar; + pba_barmskn_t barmask; + + FAPI_INF("Called with index %x, address 0x%16llX, mask 0x%16llX scope 0x%16llX", + i_index, i_pba_bar_addr, i_pba_bar_mask, i_pba_cmd_scope); + + // check if pba_bar scope in range + if ( i_pba_cmd_scope > PBA_CMD_SCOPE_FOREIGN1 ) + { + FAPI_ERR("ERROR: PB Command Scope out of Range"); + FAPI_SET_HWP_ERROR(l_rc, RC_PROC_PBA_BAR_SCOPE_OUT_OF_RANGE); + return l_rc; + } + + // check if pba_addr amd pba_mask are within range, high order bits checked, not low order! + // this means if we need a check for "is this value on the correct boundary value => needs to be implemented + if ( (BAR_ADDR_RANGECHECK_HIGH & i_pba_bar_addr) != 0x0ull) + { + FAPI_ERR("ERROR: Address out of Range"); + FAPI_SET_HWP_ERROR(l_rc, RC_PROC_PBA_ADDR_OUT_OF_RANGE); + return l_rc; + } + if ( (BAR_MASK_RANGECHECK_HIGH & i_pba_bar_mask) != 0x0ull) + { + FAPI_ERR("ERROR: Mask out of Range"); + FAPI_SET_HWP_ERROR(l_rc, RC_PROC_PBA_BAR_MASK_OUT_OF_RANGE); + return l_rc; + } + + // put the parameters into the correct fields + bar.fields.cmd_scope = i_pba_cmd_scope; + bar.fields.addr = i_pba_bar_addr; + barmask.fields.mask = i_pba_bar_mask; + + FAPI_INF("bar.fields address 0x%16llX, scope 0x%16llX", + bar.fields.addr, bar.fields.cmd_scope); + + // Write the BAR + l_ecmdRc |= data.setDoubleWord(0, bar.value); + if (l_ecmdRc) + { + FAPI_ERR("Error (0x%x) setting up ecmdDataBufferBase", l_ecmdRc); + l_rc.setEcmdError(l_ecmdRc); + return l_rc; + } + +// $$ FAPI_DBG(" PBA_BAR: %s", data.genHexLeftStr(0,64).c_str()); + l_rc = fapiPutScom(i_target, PBA_BARs[i_index], data); + if(l_rc) + { + FAPI_ERR("PBA_BAR Putscom failed"); + return l_rc; + } + + // Write the MASK + l_ecmdRc |= data.setDoubleWord(0, barmask.value); + if (l_ecmdRc) + { + FAPI_ERR("Error (0x%x) setting up ecmdDataBufferBase", l_ecmdRc); + l_rc.setEcmdError(l_ecmdRc); + return l_rc; + } + +// $$ FAPI_DBG(" PBA_BARMSK: %s", data.genHexLeftStr(0,64).c_str()); + l_rc = fapiPutScom(i_target, PBA_BARMSKs[i_index], data); + if(l_rc) + { + FAPI_ERR("PBA_MASK Putscom failed"); + return l_rc; + } + + return l_rc; +} + + +} //end extern C + diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config.H b/src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config.H new file mode 100644 index 000000000..f83f8a491 --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config.H @@ -0,0 +1,57 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +# + +//------------------------------------------------------------------------------ +// *! (C) Copyright International Business Machines Corp. 2011 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//------------------------------------------------------------------------------ +// *! OWNER NAME: Klaus P. Gungl Email: kgungl@de.ibm.com +// *! +// *! General Description: +// *! +// *! include file for proc_pba_bar_config +// *! +//------------------------------------------------------------------------------ +// + + +// function pointer typedef definition for HWP call support +typedef fapi::ReturnCode (*proc_pba_bar_config_FP_t) (const fapi::Target&, + uint32_t, + uint64_t, + uint64_t, + uint64_t); + +extern "C" +{ + +fapi::ReturnCode +proc_pba_bar_config (const fapi::Target& i_target, + uint32_t index, + uint64_t pba_bar_addr, + uint64_t pba_bar_mask, + uint64_t pba_cmd_scope); +} diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config_errors.xml b/src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config_errors.xml new file mode 100644 index 000000000..d5c19db97 --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config_errors.xml @@ -0,0 +1,56 @@ +<!-- IBM_PROLOG_BEGIN_TAG + This is an automatically generated prolog. + + $Source: src/usr/hwpf/hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config_errors.xml $ + + IBM CONFIDENTIAL + + COPYRIGHT International Business Machines Corp. 2012 + + p1 + + Object Code Only (OCO) source materials + Licensed Internal Code Source Materials + IBM HostBoot Licensed Internal Code + + The source code for this program is not published or other- + wise divested of its trade secrets, irrespective of what has + been deposited with the U.S. Copyright Office. + + Origin: 30 + + IBM_PROLOG_END_TAG --> +<!-- Error definitions for proc_pba_bar_config procedure --> +<hwpErrors> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROC_PBA_BAR_INDEX_OUT_OF_RANGE</rc> + <description>pba bar index out of range, allowed is 0 to 3</description> + </hwpError> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROC_PBA_BAR_SCOPE_OUT_OF_RANGE</rc> + <description>pba bar scope out of range, allowed is 0 to 7</description> + </hwpError> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROC_PBA_ADDR_OUT_OF_RANGE</rc> + <description>pba bar scope out of range, allowed is 0 to 7</description> + </hwpError> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROC_PBA_BAR_MASK_OUT_OF_RANGE</rc> + <description>pba bar mask out of range. .</description> + </hwpError> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROC_PBA_BAR_MODE_NOT_SUPPORTED</rc> + <description>pba bar procedure mode is not supported .</description> + </hwpError> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROC_PBA_BAR_PUTSCOM_FAILED</rc> + <description>pba bar putscom failed .</description> + </hwpError> + <!-- *********************************************************************** --> +</hwpErrors> diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_pba_init.H b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_pba_init.H new file mode 100644 index 000000000..7cbffb392 --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_pba_init.H @@ -0,0 +1,209 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_pba_init.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ + + +//------------------------------------------------------------------------------ +// *! (C) Copyright International Business Machines Corp. 2011 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//------------------------------------------------------------------------------ +// *! OWNER NAME: Klaus P. Gungl Email: kgungl@de.ibm.com +// *! +// *! General Description: +// *! +// *! include file for pba_init with constants, definitions, prototypes +// *! +//------------------------------------------------------------------------------ +// + +#ifndef _PROC_PBAINIT_H_ +#define _PROC_PBAINIT_H_ + +#include "p8_scom_addresses.H" + +typedef fapi::ReturnCode (*proc_pba_init_FP_t) (const fapi::Target& , uint64_t ); + +// constant definitions for valid command scope. LIMIT is used by setup routine for plausibility checking. + +#define PBA_CMD_SCOPE_NODAL 0x00 +#define PBA_CMD_SCOPE_GROUP 0x01 +#define PBA_CMD_SCOPE_SYSTEM 0x02 +#define PBA_CMD_SCOPE_RGP 0x03 +#define PBA_CMD_SCOPE_FOREIGN0 0x04 +#define PBA_CMD_SCOPE_FOREIGN1 0x05 +#define PBA_CMD_SCOPE_LIMIT 0x06 + +enum cmd_scope_t +{ + CMD_SCOPE_NODAL, + CMD_SCOPE_GROUP, + CMD_SCOPE_SYSTEM, + CMD_SCOPE_RGP, + CMD_SCOPE_FOREIGN0, + CMD_SCOPE_FOREIGN1 +}; +// enum cmd_scope_type {NODAL, GROUP, SYSTEM, RGP, FOREIGN0, FOREIGN1 }; + + +// addresses of PBA and PBABAR, actually a duplicate of definitions in "p8_scom_addresses.H" but here an array to be indexed. +const uint64_t PBA_BARs[4] = +{ + PBA_BAR0_0x02013F00, + PBA_BAR1_0x02013F01, + PBA_BAR2_0x02013F02, + PBA_BAR3_0x02013F03 +}; + +const uint64_t PBA_BARMSKs[4] = +{ + PBA_BARMSK0_0x02013F04, + PBA_BARMSK1_0x02013F05, + PBA_BARMSK2_0x02013F06, + PBA_BARMSK3_0x02013F07 +}; + +const uint64_t PBA_SLVCTLs[4] = +{ + PBA_SLVCTL0_0x00064004, + PBA_SLVCTL1_0x00064005, + PBA_SLVCTL2_0x00064006, + PBA_SLVCTL3_0x00064007}; + +// bar mask is valid for bits 23 to 43, in a 64bit value this is +// 1 2 3 4 5 6 +// 0123456789012345678901234567890123456789012345678901234567890123 +// 0000000000000000000000011111111111111111111100000000000000000000 +// 0 0 0 0 0 1 F F F F F 0 0 0 0 0 +// 0000000000000011111111111111111111111111111100000000000000000000 +// 0 0 0 3 F F F F F F F 0 0 0 0 0 +// 0123456701234567 +#define BAR_MASK_LIMIT 0x000001FFFFF00000ull +#define BAR_ADDR_LIMIT 0x0003FFFFFFF00000ull + +// structure of values for cmd_scope, pba and pbabar initialization +typedef struct { + cmd_scope_t cmd_scope; + uint64_t addr; + uint64_t size; +} struct_pba_bar_msk_scope_init_type; + +typedef struct { + struct_pba_bar_msk_scope_init_type regs0; + struct_pba_bar_msk_scope_init_type regs1; + struct_pba_bar_msk_scope_init_type regs2; + struct_pba_bar_msk_scope_init_type regs3; +} pba_init_type; + +typedef struct { + unsigned long reserved_3:20; + unsigned long addr:30; + unsigned short reserved_2:10; + char reserved_1:1; + uint8_t cmd_scope:3; +} struct_pba_bar_fields_type; + +typedef struct { + unsigned long reserved_1:23; + unsigned long mask:21; + unsigned long reserved_2:20; +} struct_pba_barmsk_fields_type; + +typedef union { + struct_pba_bar_fields_type fields; + uint64_t value; +} bar_reg_type; + +typedef union { + struct_pba_barmsk_fields_type fields ; + uint64_t value; +} barmsk_reg_type; + +typedef struct { + bar_reg_type bar_reg; + barmsk_reg_type barmsk_reg; +} struct_pba_bar_init_type; + + +typedef struct { + struct struct_pba_bar{ + char cmd_scope:3; + char reserved_1:1; + unsigned short reserved_2:10; + unsigned long addr:30; + unsigned long reserved_3:20; + }; + struct struct_pba_barmsk{ + unsigned long reserved_1:23; + unsigned long mask:21; + unsigned long reserved_2:20; + }; +} struct_pba_bar_init_type_1; + +typedef struct { + struct_pba_bar_init_type pba_bar0_init; + struct_pba_bar_init_type pba_bar1_init; + struct_pba_bar_init_type pba_bar2_init; + struct_pba_bar_init_type pba_bar3_init; +} struct_all_pba_bar_init_type; + + +typedef uint64_t pba_slvctl_type; + + +typedef union pbaxcfg_typ{ + uint64_t value; + struct { + unsigned long reserved_0 :20; + unsigned char ATTR_PM_PBAX_RCV_RESERV_TIMEOUT :5 ; + unsigned long reserved_1 :2; + unsigned char ATTR_PM_PBAX_SND_RETRY_COUNT_OVERCOMMIT_ENABLE :1 ; + unsigned short ATTR_PM_PBAX_SND_RETRY_THRESHOLD :8 ; + unsigned short ATTR_PM_PBAX_SND_RESERV_TIMEOUT :5 ; + unsigned long reserved_2 :23 ; + } fields; +} pbaxcfg_t; + + + + +// ---------------------------------------------------------------------- +// Function prototypes +// ---------------------------------------------------------------------- + +extern "C" +{ + +fapi::ReturnCode +proc_pba_init (const fapi::Target& i_target, + uint64_t mode + ); + + +} // extern "C" + + + +#endif // _PROC_PBAINITQ_H_ + + diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_pm.H b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_pm.H new file mode 100644 index 000000000..c65fb50a7 --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_pm.H @@ -0,0 +1,74 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_pm.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +// $Id: proc_pm.H,v 1.4 2012/05/22 14:05:53 jimyac Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/proc_pm.H,v $ +//------------------------------------------------------------------------------ +// *| +// *! (C) Copyright International Business Machines Corp. 2011 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +// *| +// *! TITLE : proc_pm.H +// *! DESCRIPTION : Common header for Power Manangement procedures +// *! +// *! OWNER NAME : Greg Still Email: stillgs@us.ibm.com +// *! BACKUP NAME : Jim Yacynych Email: jimyac@us.ibm.com +// *! +//------------------------------------------------------------------------------ + +#ifndef _PROC_PM_H_ +#define _PROC_PM_H_ + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ + +#include <fapi.H> + +#include "p8_scom_addresses.H" + + +extern "C" { + +//------------------------------------------------------------------------------ +// Constant definitions +//------------------------------------------------------------------------------ + + +#ifndef _PROC_PM_FLOW_MODE +#define _PROC_PM_FLOW_MODE +enum PROC_PM_FLOW_MODE { + PM_CONFIG = 0x1, + PM_RESET = 0x2, + PM_INIT = 0x3, + PM_SETUP = 0x4, + PM_SETUP_PIB = 0x5, + PM_SETUP_ALL = 0x6 + }; +#endif // _PROC_PM_FLOW_MODE + + +} // extern "C" + +#endif // _PROC_PM_H_ diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar.C b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar.C new file mode 100644 index 000000000..5e91313c1 --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar.C @@ -0,0 +1,463 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar.C $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +// $Id: proc_set_pore_bar.C,v 1.7 2012/07/25 12:26:28 stillgs Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/proc_set_pore_bar.C,v $ +//------------------------------------------------------------------------------ +// *! (C) Copyright International Business Machines Corp. 2011 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//------------------------------------------------------------------------------ +// *! OWNER NAME: Greg Still Email: stillgs@us.ibm.com +// *! +/// \file proc_set_pore_bar.C +/// \brief Set up the Sleep/Winkle (SLW) PORE Memory Relocation (MRR) and +/// Table Base Address (TBA) for accessing the SLW image +/// +/// High-level procedure flow: +/// \verbatim +/// +/// Address and size of SLW image for the target (chip) is passed based on +/// where the caller has placed the image for this target in the platform +/// memory. +/// +/// The Base Address (BAR) and a mask for the region in which the SLW +/// image is placed is passed. This is used to establish the PBA BAR and +/// mask hardware to set the legal bounds for SLW accesses. +/// +/// The BAR defines address bits 14:43 in natural bit alignment (eg no shifting) +/// The Mask defines validity for bits 23:43 in natural bit alignment. This +/// is a "thermometer" mask to define a power of 2 size. +/// +/// A "1" in the mask indicates that bit location comes from the SLW; a "0" +/// indicates the bit comes from the BAR. Thus, the size of the region is +/// ((mask+1)) MB. (eg the mask value 7 yields an 8MB region) +/// +/// Check that passed address is within the 50 bit real address range +/// Check that image address + image size does not extend past the 50 bit +/// boundary +/// +/// Read image link address at image offset 0x10 +/// Link Address(0:1) is the OCI region that will invoke the MRR. These +/// are set into MRR(30:31). +/// Calculate MRR address (32:63) = image address - link address (32 bit) +/// Store MRR to PORE SLW +/// +/// Call proc_pba_bar_config to set up PBA BAR 2 with the address and +/// size of the SLW region as passed via calling parameters +/// i_mem_bar and i_mem_mask. +/// +/// Procedure Prereq: +/// - SLW image memory region has been allocated and XIP image loaded. +/// \endverbatim +/// +//------------------------------------------------------------------------------ + + +// ---------------------------------------------------------------------- +// Includes +// ---------------------------------------------------------------------- +#include <fapi.H> +#include "p8_scom_addresses.H" +#include "proc_set_pore_bar.H" +#include "proc_pm.H" +#include "proc_pba_init.H" +#include "proc_pba_bar_config.H" +#include "sbe_xip_image.h" + + +extern "C" { + +using namespace fapi; + +// ---------------------------------------------------------------------- +// Constant definitions +// ---------------------------------------------------------------------- + +const uint32_t SLW_PBA_BAR = 2; + +// ---------------------------------------------------------------------- +// Global variables +// ---------------------------------------------------------------------- + +// ---------------------------------------------------------------------- +// Function prototypes +// ---------------------------------------------------------------------- + +// ---------------------------------------------------------------------- +// Function definitions +// ---------------------------------------------------------------------- + + +/// \param[in] i_target Procesor Chip target +/// \param[in] i_image Platform memory pointer where image is +/// located +/// \param[in] i_mem_bar Base address of the region where image is located +/// \param[in] i_mem_mask Mask that defines which address bits of the +/// BAR apply such to define the region size +/// \param[in] i_mem_type Defines where the SLW image was loaded. See +/// proc_set_pore_bar.H enum for valid values. +/// +/// \retval SUCCESS +/// \retval RC_PROCPM_POREBAR_IMAGE_BRANCH_VALUE_ERROR +/// \retval RC_PROCPM_POREBAR_LOC_ERROR +/// \retval RC_PROCPM_POREBAR_IMAGE_ADDR_ERROR (future version) +/// \retval RC_PROCPM_POREBAR_IMAGE_PLACEMENT_ERROR (future version) + +fapi::ReturnCode +proc_set_pore_bar( const fapi::Target& i_target, + void *i_image, + uint64_t i_mem_bar, + uint64_t i_mem_mask, + uint32_t i_mem_type) +{ + fapi::ReturnCode rc; + uint32_t l_ecmdRc = 0; + ecmdDataBufferBase data; + + uint64_t image_address; + uint64_t image_size; +// uint64_t region_begin_address; +// uint64_t region_end_address; + uint64_t region_masked_address; +// uint64_t region_inverted_mask; +// uint64_t computed_image_address; +// uint64_t computed_last_image_address; + + uint64_t slw_branch_table_address; + + // Hardcoded use of PBA BAR and Slave + const uint32_t pba_bar = PBA_BAR2; + const uint32_t pba_bar_slw = PBA_SLW_BAR2; + const uint32_t pba_slave = PBA_SLAVE2; + + const uint64_t slw_pba_cmd_scope = 0x2; // Set to system + + + // ----------------------------------------------------------------- + + FAPI_INF("Executing proc_set_pore_bar..."); + image_address = (uint64_t) i_image; + FAPI_DBG("Passed address 0x%16llX ", image_address); + + // Get the Table Base Address from the image + l_ecmdRc = sbe_xip_get_scalar((void*) i_image, + "slw_branch_table", + &slw_branch_table_address); + if (l_ecmdRc) + { + FAPI_ERR("Get XIP of slw_branch_table failed. rc = %x\n", l_ecmdRc); + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_POREBAR_IMAGE_BRANCH_VALUE_ERROR); + return rc; + } + FAPI_DBG("slw_branch_table_address: %16llX", slw_branch_table_address); + + // Initialize the ecmdDataBuffer + l_ecmdRc |= data.clear(); + l_ecmdRc |= data.setBitLength(64); + if(l_ecmdRc) + { + FAPI_ERR("Error (0x%x) setting up ecmdDataBufferBase", l_ecmdRc); + rc.setEcmdError(l_ecmdRc); + return rc; + } + + + // Setup the the table base address register + // + // Table Base Address Register layout + // 16 Interface (0=PIB, 1=OCI) + // 17 Reserved + // 18:23 Chiplet ID (used only for PIB fetch; unused for OCI)-SLW unused + // 24:27 PIB ID (used only for PIB fetch; unused for OCI)-SLW unused + // 28:31 PORT ID (used only for PIB fetch; unused for OCI)-SLW unused + // 32:64 Table base address for jump table + // + // 1 2 3 3 6 + // 6789012345678901 2-----3 + // 1 OCI + // 0 + // 000000 Chiplet ID + // 0000 PIB ID + // 0000 PORT ID + // + // For SLW images that will run on PORE-SLW, the PORT ID is set to C + // + // + + // Set the table base address (32:63) with passed value + l_ecmdRc |= data.setDoubleWord( 0, slw_branch_table_address); + if(l_ecmdRc) + { + FAPI_ERR("Error (0x%x) setting up ecmdDataBufferBase", l_ecmdRc); + rc.setEcmdError(l_ecmdRc); + return rc; + } + rc = fapiPutScom(i_target, PORE_SLW_TABLE_BASE_ADDR_0x00068008, data); + if (rc) + { + FAPI_ERR("Put SCOM error for Table Base Address"); + return rc; + } + FAPI_INF("SLW PORE Table Base Address set to 0x%16llx", data.getDoubleWord(0)); + + + + // Setup the memory relocation register + // + // This is hardcoded as the SLW image build process has all images to be: + // 1) Relocatable and thus must have the region match bits set + // 2) Built for region 0x80000XXX + // + // MRR Layout + // 30:31: Memory Reloc Region - 2 MSbs of 32 bit address that + // defines the region match + // 32:51 Memory Relocation Base Address added to 0:19 of the OCI + // address + // + // Table Base Address Register layout + // 16 Interface (0=PIB, 1=OCI) + // 17 Reserved + // 18:23 Chiplet ID (used only for PIB fetch; unused for OCI)-SLW unused + // 24:27 PIB ID (used only for PIB fetch; unused for OCI)-SLW unused + // 28:31 PORT ID (used only for PIB fetch; unused for OCI)-SLW unused + // 32:64 Table base address for jump table + // + // 1 2 3 3 6 + // 6789012345678901 2-----3 + // 1 OCI + // 0 + // 000000 Chiplet ID + // 0000 PIB ID + // 0000 PORT ID + // + // For SLW images that will run on PORE-SLW, the PORT ID is set to C in + // the image but this is unused by the hardware. + + l_ecmdRc |= data.flushTo0(); + + // Set 30:31 to 10 to yield a region of 0x8XXXXXXX (eg unused OCI region) + l_ecmdRc |= data.setBit( 30, 1); + + if(l_ecmdRc) + { + FAPI_ERR("Error (0x%x) setting up ecmdDataBufferBase", l_ecmdRc); + rc.setEcmdError(l_ecmdRc); + return rc; + } + + // SLW image has effective addresses in the form of 0x8XXXXXXX. + // The PORE memory relocation function adds the mem_reloc(32:52) to + // effective address 0:19 to form the real address where: + // effective address(0:1) defines the region: 00 = memory/L3, 11 = SRAM + // effective address(2:3) defines the PBA BAR to use (if memory/L3) + + // Set the Memory Relocation Base based on the placement of the SLW image + if (i_mem_type == SLW_SRAM) + { + // Set the beginning of 512KB SRAM tank. + + FAPI_DBG("SLW PORE Memory Relocation Register before SRAM 0x%16llx", data.getDoubleWord(0)); + + l_ecmdRc |= data.setOr(0x7FF80<<12, 32, 20); + if(l_ecmdRc) + { + FAPI_ERR("Error (0x%x) manipulating ecmdDataBufferBase", l_ecmdRc); + rc.setEcmdError(l_ecmdRc); + return rc; + } + } + else if (i_mem_type == SLW_MEMORY || i_mem_type == SLW_L3) + { + // The 00 (from the buffer flush) in 0:1 goes toward PBA (memory or L3) + // Set to use the PBA with BAR(0:3) encoded in bits 2:3 (eg shift of 30) + // 0x80000 + 0xA0000 => 20000 (upper overflow discarded) + // The 00 in 0:1 goes toward PBA; 2:3 for PBA BAR 2 + FAPI_DBG("SLW PORE PBA BAR %x", pba_bar_slw); + FAPI_DBG("SLW PORE Memory Relocation Register before MEM 0x%16llx", data.getDoubleWord(0)); + + l_ecmdRc |= data.setOr(pba_bar_slw<<28, 32, 20); + if(l_ecmdRc) + { + FAPI_ERR("Error (0x%x) manipulating ecmdDataBufferBase", l_ecmdRc); + rc.setEcmdError(l_ecmdRc); + return rc; + } + + FAPI_DBG("SLW PORE Memory Relocation Register after MEM 0x%16llx", data.getDoubleWord(0)); + + // Check that the bar address passed is 1MB aligned (eg bits 44:63 are zero) + // + region_masked_address = i_mem_bar & 0x00000000000FFFFF; + if (region_masked_address != 0 ) + { + FAPI_ERR("SLW BAR address is not 1MB aligned: 0x%16llx", i_mem_bar ); + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_POREBAR_PBABAR_ERROR); + return rc; + } + + + // The PBA Mask indicates which bits from 23:43 (1MB grandularity) are + // enabled to be passed from the OCI addresses. Inverting this mask + // indicates which address bits are going to come from the PBA BAR value. + // The image address (the starting address) must match these post mask bits + // to be resident in the range. + // + // Starting bit number: 64 bit Big Endian + // 12223344 + // 60482604 + // region_inverted_mask = i_mem_mask ^ BAR_MASK_LIMIT; // XOR + + + // Check that the image address passed is within the memory region that + // is also passed. + // + // The PBA Mask indicates which bits from 23:43 (1MB grandularity) are + // enabled to be passed from the OCI addresses. Inverting this mask + // indicates which address bits are going to come from the PBA BAR value. + // The image address (the starting address) must match these post mask bits + // to be resident in the range. + // + // Starting bit number: 64 bit Big Endian + // 12223344 + // 60482604 + // region_inverted_mask = i_mem_mask ^ BAR_MASK_LIMIT; // XOR + + // Set bits 14:22 as these are unconditional address bits + //region_inverted_mask = region_inverted_mask | BAR_ADDR_UNMASKED; + //computed_image_address = region_inverted_mask && image_address; + // Need to AND the address + //if (computed_image_address != i_mem_bar ) + //{ + // FAPI_ERR("SLW image address check failure. "); + // FAPI_SET_HWP_ERROR(rc, RC_PROCPM_POREBAR_IMAGE_ADDR_ERROR); + // return rc; + //} + + + // Additionally, the size of the image must not extend beyond the above + // masked range either. + + // Get the image size from the image itself + l_ecmdRc = sbe_xip_get_scalar((void*) i_image, + "image_size", + &image_size); + + if (l_ecmdRc) + { + FAPI_ERR("Get of XIP Image size failed"); + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_POREBAR_IMAGE_SIZE_ERROR); + return rc; + } + + FAPI_DBG("SLW image size: 0x%08llX", image_size ); + // computed_last_image_address = image_address + image_size; + // + // if (computed_last_image_address > region_end_address) + // { + // FAPI_ERR("SLW image placement error."); + // FAPI_SET_HWP_ERROR(rc, RC_PROCPM_POREBAR_IMAGE_PLACEMENT_ERROR); + // return rc; + // } + + } + else + { + FAPI_ERR("Invalid image location passed %x ", i_mem_type); + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_POREBAR_LOC_ERROR); + return rc; + } + + FAPI_INF("SLW PORE Memory Relocation Register set to 0x%16llx", data.getDoubleWord(0)); + rc = fapiPutScom(i_target, PORE_SLW_MEMORY_RELOC_0x00068016, data); + if (rc) + { + FAPI_ERR("Put SCOM error for Memory Relocation Address"); + return rc; + } + + + + + + + FAPI_DBG("Calling pba_bar_config to BAR %x Addr: 0x%16llX Mask: 0x%16llX", + pba_bar, i_mem_bar, i_mem_mask); + + // Set the PBA BAR for the SLW region + FAPI_EXEC_HWP(rc, proc_pba_bar_config, i_target, + pba_bar, + i_mem_bar, + i_mem_mask, + slw_pba_cmd_scope); + if(rc) { return rc; } + + // Set the PBA Slave to use the above BAR + // \todo Does not yet comprehend the 24x7 setting to allow writing!! + // + // enable = 1; // Enable the slave + // mid_match_value=0x4; // PORE-SLW engine + // mid_care_mask=0x7; // Only the PORE-SLW + // write_ttype=0; // DMA - though NA + // read_ttype=0; // CL_RD_NC + // read_prefetch_ctl=0; // Auto Early + // buf_invalidate_ctl=0; // Disabled + // buf_alloc_w=0; // SLW does not write. 24x7 will + // buf_alloc_a=0; // SLW uses Buf A + // buf_alloc_b=0; // SLW does not use buffer B + // buf_alloc_c=0; // SLW does not use buffer C + // dis_write_gather=0; // SLW does not write. \todo 24x7 + // wr_gather_timeout=0; // SLW does not write \todo 24x7 + // write_tsize=0; // SLW does not write \todo 24x7 + // extaddr=0; // Bits 23:36. NA for SLW + // + + // Clear the data buffer (for cleanliness) + l_ecmdRc |= data.flushTo0(); + + + // set the PBASLVCTL reg + l_ecmdRc |= data.setBit(0); // Enable the slave + l_ecmdRc |= data.setBit(1); // PORE-SLW engine - 0b100 + l_ecmdRc |= data.setBit(5,3); // Care mask-only PORE-SLW + + if(l_ecmdRc) + { + FAPI_ERR("Error (0x%x) manipulating ecmdDataBufferBase for PBASLVCTL", l_ecmdRc); + rc.setEcmdError(l_ecmdRc); + return rc; + } + + FAPI_DBG(" PBA_SLVCTL%x: 0x%16llx", pba_slave, data.getDoubleWord(0)); + rc = fapiPutScom(i_target, PBA_SLVCTLs[pba_slave], data); + if (rc) + { + FAPI_ERR("Put SCOM error for PBA Slave Control"); + return rc; + } + + return rc; +} + + +} //end extern C diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar.H b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar.H new file mode 100644 index 000000000..3083ff35c --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar.H @@ -0,0 +1,123 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +// $Id: proc_set_pore_bar.H,v 1.3 2012/07/20 21:14:11 stillgs Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/proc_set_pore_bar.H,v $ +//------------------------------------------------------------------------------ +// *| +// *! (C) Copyright International Business Machines Corp. 2011 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +// *| +// *! TITLE : proc_set_pore_bar.H +// *! DESCRIPTION : Establish the BAR setup for the SLW image in the PBA as +// *! well as setting up the SLW engine with table base address +// *! and memory relocation regs in the SLW +// *! +// *! OWNER NAME : Greg Still Email: stillgs@us.ibm.com +// *! BACKUP NAME : Jim Yacynych Email: jimyac@us.ibm.com +// *! +//------------------------------------------------------------------------------ + +#ifndef _PROC_SET_PORE_BAR_H_ +#define _PROC_SET_PORE_BAR_H_ + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ + + +// function pointer typedef definition for HWP call support +typedef fapi::ReturnCode (*proc_set_pore_bar_FP_t) (const fapi::Target&, + void*, + uint64_t, + uint64_t, + uint32_t + ); + +extern "C" { + + +//------------------------------------------------------------------------------ +// Constant definitions +//------------------------------------------------------------------------------ + +enum PORE_SLW_LOC { + SLW_MEMORY = 0x0, + SLW_L3 = 0x1, + SLW_SRAM = 0x2 + }; + +// The value here will yield the appropriate nibble for accessing the PowerBus +// Regions (eg 0:1 = 00) when added to 0x8 (the SLW image effective address upper +// nibble) - 4 bit math only. +enum PORE_SLW_PBA_BAR { + PBA_SLW_BAR0 = 0x8, // 0x8 + 0x8 = 0x0 + PBA_SLW_BAR1 = 0x9, // 0x8 + 0x9 = 0x1 + PBA_SLW_BAR2 = 0xA, // 0x8 + 0xA = 0x2 + PBA_SLW_BAR3 = 0xB // 0x8 + 0xB = 0x3 + }; + +enum PORE_PBA_BAR { + PBA_BAR0 = 0x0, + PBA_BAR1 = 0x1, + PBA_BAR2 = 0x2, + PBA_BAR3 = 0x3 + }; + +enum PORE__BA_SLAVE { + PBA_SLAVE0 = 0x0, + PBA_SLAVE1 = 0x1, + PBA_SLAVE2 = 0x2, + PBA_SLAVE3 = 0x3 + }; + +//------------------------------------------------------------------------------ +// Parameter structure definitions +//------------------------------------------------------------------------------ + + + +//------------------------------------------------------------------------------ +// Function prototype +//------------------------------------------------------------------------------ +/// \param[in] i_target Procesor Chip target +/// \param[in] i_image Platform memory pointer where image is +/// located +/// \param[in] i_mem_bar Base address of the region where image is located +/// \param[in] i_mem_mask Mask that defines which address bits of the +/// BAR apply such to define the region size +/// \param[in] i_mem_type Defines where the SLW image was loaded. See +/// proc_set_pore_bar.H enum for valid values. + +fapi::ReturnCode +proc_set_pore_bar( const fapi::Target& i_target, + void *i_image, + uint64_t i_mem_bar, + uint64_t i_mem_mask, + uint32_t i_mem_type); + + +} // extern "C" + +#endif // _PROC_SET_PORE_BAR_H_ diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar_errors.xml b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar_errors.xml new file mode 100644 index 000000000..d053b9fcb --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar_errors.xml @@ -0,0 +1,56 @@ +<!-- IBM_PROLOG_BEGIN_TAG + This is an automatically generated prolog. + + $Source: src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar_errors.xml $ + + IBM CONFIDENTIAL + + COPYRIGHT International Business Machines Corp. 2012 + + p1 + + Object Code Only (OCO) source materials + Licensed Internal Code Source Materials + IBM HostBoot Licensed Internal Code + + The source code for this program is not published or other- + wise divested of its trade secrets, irrespective of what has + been deposited with the U.S. Copyright Office. + + Origin: 30 + + IBM_PROLOG_END_TAG --> +<!-- Error definitions for proc_set_pore_bar procedure --> +<hwpErrors> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROCPM_POREBAR_IMAGE_BRANCH_VALUE_ERROR</rc> + <description>XIP access of branch table failed in proc_set_pore_bar</description> + </hwpError> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROCPM_POREBAR_LOC_ERROR</rc> + <description>Invalid image location passed to proc_set_pore_bar</description> + </hwpError> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROCPM_POREBAR_PBABAR_ERROR</rc> + <description>PBA BAR image location passed to proc_set_pore_bar</description> + </hwpError> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROCPM_POREBAR_IMAGE_SIZE_ERROR</rc> + <description>XIP access to size value failed in proc_set_pore_bar</description> + <description>Image address plus image size overflows PBA region in proc_set_pore_bar</description> + </hwpError> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROCPM_POREBAR_IMAGE_PLACEMENT_ERROR</rc> + <description>Image address plus image size overflows PBA region in proc_set_pore_bar</description> + </hwpError> + <!-- *********************************************************************** --> + <hwpError> + <rc>RC_PROCPM_POREBAR_IMAGE_ADDR_ERROR</rc> + <description>Image address not in PBA BAR region in proc_set_pore_bar</description> + </hwpError> +</hwpErrors> diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/sbe_xip_image.h b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/sbe_xip_image.h new file mode 100644 index 000000000..4109659ea --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/sbe_xip_image.h @@ -0,0 +1,1749 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/sbe_xip_image.h $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +#ifndef __SBE_XIP_IMAGE_H +#define __SBE_XIP_IMAGE_H + +// $Id: sbe_xip_image.h,v 1.17 2012/06/12 13:30:28 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/sbe/sbe_xip_image.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2011 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- +// *! OWNER NAME: Bishop Brock Email: bcbrock@us.ibm.com +//------------------------------------------------------------------------------ + +/// \file sbe_xip_image.h +/// \brief Everything related to creating and manipulating SBE-XIP binary +/// images. + +#include "fapi_sbe_common.H" + +/// Current version (fields, layout, sections) of the SBE_XIP header +/// +/// If any changes are made to this file or to sbe_xip_header.H, please update +/// the header version and follow-up on all of the error messages. + +#define SBE_XIP_HEADER_VERSION 8 + +/// \defgroup sbe_xip_magic_numbers SBE-XIP magic numbers +/// +/// An SBE-XIP magic number is a 64-bit constant. The 4 high-order bytes +/// contain the ASCII characters "XIP " and identify the image as an SBE-XIP +/// image, while the 4 low-order bytes identify the type of the image. +/// +/// @{ + +#define SBE_XIP_MAGIC 0x58495020 // "XIP " +#define SBE_BASE_MAGIC ULL(0x5849502042415345) // "XIP BASE" +#define SBE_SEEPROM_MAGIC ULL(0x584950205345504d) // "XIP SEPM" +#define SBE_CENTAUR_MAGIC ULL(0x58495020434e5452) // "XIP CNTR" + +/// @} + + +/// \defgroup sbe_xip_sections SBE-XIP Image Section Indexes +/// +/// These constants define the order that the SbeXipSection structures appear +/// in the header, which is not necessarily the order the sections appear in +/// the binary image. Given that SBE-XIP image contents are tightly +/// controlled, we use this simple indexing scheme for the allowed sections +/// rather than a more general approach, e.g., allowing arbitrary sections +/// identified by their names. +/// +/// @{ + +// -*- DO NOT REORDER OR EDIT THIS SET OF CONSTANTS WITHOUT ALSO EDITING -*- +// -*- THE ASSEMBLER LAYOUT IN sbe_xip_header.S. -*- + +#define SBE_XIP_SECTION_HEADER 0 +#define SBE_XIP_SECTION_FIXED 1 +#define SBE_XIP_SECTION_FIXED_TOC 2 +#define SBE_XIP_SECTION_IPL_TEXT 3 +#define SBE_XIP_SECTION_IPL_DATA 4 +#define SBE_XIP_SECTION_TEXT 5 +#define SBE_XIP_SECTION_DATA 6 +#define SBE_XIP_SECTION_TOC 7 +#define SBE_XIP_SECTION_STRINGS 8 +#define SBE_XIP_SECTION_HALT 9 +#define SBE_XIP_SECTION_PIBMEM0 10 +#define SBE_XIP_SECTION_PIBMEM1 11 +#define SBE_XIP_SECTION_RINGS 12 +#define SBE_XIP_SECTION_SLW 13 +#define SBE_XIP_SECTION_RESERVED_1 14 +#define SBE_XIP_SECTION_RESERVED_0 15 + +#define SBE_XIP_SECTIONS 16 + +/// @} + +#ifndef __ASSEMBLER__ + +/// Applications can expand this macro to create an array of section names. +#define SBE_XIP_SECTION_NAMES(var) \ + const char* var[] = { \ + ".header", \ + ".fixed", \ + ".fixed_toc", \ + ".ipl_text", \ + ".ipl_data", \ + ".text", \ + ".data", \ + ".toc", \ + ".strings", \ + ".halt", \ + ".pibmem0", \ + ".pibmem1", \ + ".rings", \ + ".slw", \ + ".reserved_1", \ + ".reserved_0" \ + } + +/// Applications can use this macro to safely index the array of section +/// names. +#define SBE_XIP_SECTION_NAME(var, n) \ + ((((n) < 0) || ((n) > (int)(sizeof(var) / sizeof(char*)))) ? \ + "Bug : Invalid SBE-XIP section name" : var[n]) + + +#endif /* __ASSEMBLER__ */ + + +/// Maximum section alignment for SBE-XIP sections +#define SBE_XIP_MAX_SECTION_ALIGNMENT 128 + +/// defgroup sbe_xip_toc_types SBE-XIP Table of Contents data types +/// +/// These are the data types stored in the \a iv_type field of the SbeXipToc +/// objects. These must be defined as manifest constants because they are +/// required to be recognized as manifest constants in C (as opposed to C++) +/// code. +/// +/// NB: The 0x0 code is purposefully left undefined to catch bugs. +/// +/// @{ + +/// Data is a single unsigned byte +#define SBE_XIP_UINT8 0x01 + +/// Data is a 32-bit unsigned integer +#define SBE_XIP_UINT32 0x02 + +/// Data is a 64-bit unsigned integer +#define SBE_XIP_UINT64 0x03 + +/// Data is a 0-byte terminated ASCII string +#define SBE_XIP_STRING 0x04 + +/// Data is an address +#define SBE_XIP_ADDRESS 0x05 + +/// The maximum type number +#define SBE_XIP_MAX_TYPE_INDEX 0x05 + +/// Applications can expand this macro to get access to string forms of the +/// SBE-XIP data types if desired. +#define SBE_XIP_TYPE_STRINGS(var) \ + const char* var[] = { \ + "Illegal 0 Code", \ + "SBE_XIP_UINT8", \ + "SBE_XIP_UINT32", \ + "SBE_XIP_UINT64", \ + "SBE_XIP_STRING", \ + "SBE_XIP_ADDRESS", \ + } + +/// Applications can expand this macro to get access to abbreviated string +/// forms of the SBE-XIP data types if desired. +#define SBE_XIP_TYPE_ABBREVS(var) \ + const char* var[] = { \ + "Illegal 0 Code", \ + "u8 ", \ + "u32", \ + "u64", \ + "str", \ + "adr", \ + } + +/// Applications can use this macro to safely index either array of SBE-XIP +/// type strings. +#define SBE_XIP_TYPE_STRING(var, n) \ + (((n) > (sizeof(var) / sizeof(char*))) ? \ + "Invalid SBE-XIP type specification" : var[n]) + +/// @} + + +/// Final alignment constraint for SBE-XIP images. +/// +/// PORE images are required to be multiples of 8 bytes in length, to +/// gaurantee that the PoreVe will be able to complete any 8-byte load/store. +#define SBE_XIP_FINAL_ALIGNMENT 8 + + +//////////////////////////////////////////////////////////////////////////// +// C Definitions +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} /* So __cplusplus doesn't mess w/auto-indent */ +#endif + +/// SBE-XIP Section information +/// +/// This structure defines the data layout of section table entries in the +/// SBE-XIP image header. + +// -*- DO NOT REORDER OR EDIT THIS STRUCTURE DEFINITION WITHOUT ALSO -*- +// -*- EDITING THE ASSEMBLER LAYOUT IN sbe_xip_header.H -*- + +typedef struct { + + /// The offset (in bytes) of the section from the beginning of the image + /// + /// In normalized images the section offset will always be 0 if the + /// section size is also 0. + uint32_t iv_offset; + + /// The size of the section in bytes, exclusive of alignment padding + /// + /// This is the size of the program-significant data in the section, + /// exclusive of any alignment padding or reserved or extra space. The + /// alignment padding (reserved space) is not represented explicitly, but + /// is only implied by the offset of any subsequent non-empty section, or + /// in the case of the final section in the image, the image size. + /// + /// Regardless of the \a iv_offset, if the \a iv_size of a section is 0 it + /// should be considered "not present" in the image. In normalized images + /// the section offset will always be 0 if the section size is also 0. + uint32_t iv_size; + + /// The required initial alignment for the section offset + /// + /// The PORE and the applications using SBE-XIP images have strict + /// alignment/padding requirements. The PORE does not handle any type of + /// unaligned instruction or data fetches. Some sections and subsections + /// must also be POWER cache-line aligned. The \a iv_alignment applies to + /// the first byte of the section. PORE images are also required to be + /// multiples of 8 bytes in length, to gaurantee that the PoreVe will be + /// able to complete any 8-byte load/store. These constraints are checked + /// by sbe_xip_validate() and enforced by sbe_xip_append(). The alignment + /// constraints may force a section to be padded, which may create "holes" + /// in the image as explained in the comments for the \a iv_size field. + /// + /// Note that alignment constraints are always checked relative to the + /// first byte of the image for in-memory images, not relative to the host + /// address. Alignment specifications are required to be a power-of-2. + uint8_t iv_alignment; + + /// Reserved structure alignment padding; Pad to 12 bytes + uint8_t iv_reserved8[3]; + +} SbeXipSection; + +/// The SbeXipSection structure is created by assembler code and is expected +/// to have the same size in C code. This constraint is checked in +/// sbe_xip_validate(). +#define SIZE_OF_SBE_XIP_SECTION 12 + + +/// SBE-XIP binary image header +/// +/// This header occupies the initial bytes of an SBE-XIP binary image. +/// The header contents are documented here, however the structure is actually +/// defined in the file sbe_xip_header.S, and these two definitions must be +/// kept consistent. +/// +/// The header is a fixed-format representation of the most critical +/// information about the image. The large majority of information about the +/// image and its contents are available through the searchable table of +/// contents. PORE code itself normally accesses the data directly through +/// global symbols. +/// +/// The header only contains information 1) required by OTPROM code (e.g., the +/// entry point); 2) required by search and updating APIs (e.g., the +/// locations and sizes of all of the sections.); a few pieces of critical +/// meta-data (e.g., information about the image build process). +/// +/// Any entries that are accessed by PORE code are required to be 64 bits, and +/// will appear at the beginning of the header. +/// +/// The header also contains bytewise offsets and sizes of all of the sections +/// that are assembled to complete the image. The offsets are relative to the +/// start of the image (where the header is loaded). The sizes include any +/// padding inserted by the link editor to guarantee section alignment. +/// +/// Every field of the header is also accesssible through the searchable table +/// of contents as documented in sbe_xip_header.S. + +// -*- DO NOT REORDER OR EDIT THIS STRUCTURE DEFINITION WITHOUT ALSO -*- +// -*- EDITING THE ASSEMBLER LAYOUT IN sbe_xip_header.S, AND WITHOUT -*- +// -*- UPDATING THE sbe_xip_translate_header() API IN sbe_xip_image.c. -*- + +typedef struct { + + ////////////////////////////////////////////////////////////////////// + // Identification - 8-byte aligned; 8 entries + ////////////////////////////////////////////////////////////////////// + + /// Contains SBE_XIP_MAGIC to identify an SBE-XIP image + uint64_t iv_magic; + + /// The offset of the SBE-XIP entry point from the start of the image + uint64_t iv_entryOffset; + + /// The base address used to link the image, as a full relocatable PORE + /// address + uint64_t iv_linkAddress; + + /// Reserved for future expansion + uint64_t iv_reserved64[5]; + + ////////////////////////////////////////////////////////////////////// + // Section Table - 4-byte aligned; 16 entries + ////////////////////////////////////////////////////////////////////// + + SbeXipSection iv_section[SBE_XIP_SECTIONS]; + + ////////////////////////////////////////////////////////////////////// + // Other information - 4-byte aligned; 8 entries + ////////////////////////////////////////////////////////////////////// + + /// The size of the image (including padding) in bytes + uint32_t iv_imageSize; + + /// Build date generated by `date +%Y%m%d`, e.g., 20110630 + uint32_t iv_buildDate; + + /// Build time generated by `date +%H%M`, e.g., 0756 + uint32_t iv_buildTime; + + /// Reserved for future expansion + uint32_t iv_reserved32[5]; + + ////////////////////////////////////////////////////////////////////// + // Other Information - 1-byte aligned; 8 entries + ////////////////////////////////////////////////////////////////////// + + /// Header format version number + uint8_t iv_headerVersion; + + /// Indicates whether the image has been normalized (0/1) + uint8_t iv_normalized; + + /// Indicates whether the TOC has been sorted to speed searching (0/1) + uint8_t iv_tocSorted; + + /// Reserved for future expansion + uint8_t iv_reserved8[5]; + + ////////////////////////////////////////////////////////////////////// + // Strings; 64 characters allocated + ////////////////////////////////////////////////////////////////////// + + /// Build user, generated by `id -un` + char iv_buildUser[16]; + + /// Build host, generated by `hostname` + char iv_buildHost[24]; + + /// Reserved for future expansion + char iv_reservedChar[24]; + +} SbeXipHeader; + + +/// A C-structure form of the SBE-XIP Table of Contents (TOC) entries +/// +/// The .toc section consists entirely of an array of these structures. +/// TOC entries are never accessed by PORE code. +/// +/// These structures store indexing information for global data required to be +/// manipulated by external tools. The actual data is usually allocated in a +/// data section and manipulated by the SBE code using global or local symbol +/// names. Each TOC entry contains a pointer to a keyword string naming the +/// data, the address of the data (or the data itself), the data type, +/// meta-information about the data, and for vectors the vector size. + +// -*- DO NOT REORDER OR EDIT THIS STRUCTURE DEFINITION WITHOUT ALSO -*- +// -*- EDITING THE ASSEMBLER MACROS (BELOW) THAT CREATE THE TABLE OF -*- +// -*- CONTENTS ENTRIES. -*- + +typedef struct { + + /// A pointer to a 0-byte terminated ASCII string identifying the data. + /// + /// When allocated by the .xip_toc macro this is a pointer to the string + /// form of the symbol name for the global or local symbol associated with + /// the data which is allocated in the .strings section. This pointer is + /// not aligned. + /// + /// When the image is normalized this pointer is replaced by the offset of + /// the string in the .strings section. + uint32_t iv_id; + + /// A 32-bit pointer locating the data + /// + /// This field is initially populated by the link editor. For scalar, + /// vector and string types this is the final relocated address of the + /// first byte of the data. For address types, this is the relocated + /// address. When the image is normalized, these addresses are converted + /// into the equivalent offsets from the beginning of the section holding + /// the data. + uint32_t iv_data; + + /// The type of the data; See \ref sbe_xip_toc_types. + uint8_t iv_type; + + /// The section containing the data; See \ref sbe_xip_sections. + uint8_t iv_section; + + /// The number of elements for vector types, otherwise 1 for scalar types + /// and addresses. + /// + /// Vectors are naturally limited in size, e.g. to the number of cores, + /// chips in a node, DD-levels etc. If \a iv_elements is 0 then no bounds + /// checking is done on get/set accesses of the data. + uint8_t iv_elements; + + /// Structure alignment padding; Pad to 12 bytes + uint8_t iv_pad; + +} SbeXipToc; + +/// The SbeXipToc structure is created by assembler code and is expected +/// to have the same size in C code. This constraint is checked in +/// sbe_xip_validate(). +#define SIZE_OF_SBE_XIP_TOC 12 + + +/// A C-structure form of hashed SBE-XIP Table of Contents (TOC) entries +/// +/// This structure was introduced in order to allow a small TOC for the .fixed +/// section to support minimum-sized SEEPROM images in which the global TOC +/// and all strings have been stripped out. In this structure the index +/// string has been replaced by a 32-bit hash, and there is no longer a record +/// of the original data name other then the hash. The section of the data is +/// assumed to be .fixed, with a maximum 16-bit offset. +/// +/// These structures are created when entries are made in the .fixed section. +/// They are created empty, then filled in during image normalization. +/// +/// This structure allows the sbe_xip_get*() and sbe_xip_set*() APIs to work +/// even on highly-stripped SEEPROM images. + +typedef struct { + + /// A 32-bit hash (FNV-1a) of the Id string. + uint32_t iv_hash; + + /// The offset in bytes from the start of the (implied) section of the data + uint16_t iv_offset; + + /// The type of the data; See \ref sbe_xip_toc_types. + uint8_t iv_type; + + /// The number of elements for vector types, otherwise 1 for scalar types + /// and addresses. + /// + /// Vectors are naturally limited in size, e.g. to the number of cores, + /// chips in a node, DD-levels etc. If \a iv_elements is 0 then no bounds + /// checking is done on get/set accesses of the data. + uint8_t iv_elements; + +} SbeXipHashedToc; + +/// The SbeXipHashedToc structure is created by assembler code and is expected +/// to have the same size in C code. This constraint is checked in +/// sbe_xip_validate(). +#define SIZE_OF_SBE_XIP_HASHED_TOC 8 + + +/// A decoded TOC entry for use by applications +/// +/// This structure is a decoded form of a normalized TOC entry, filled in by +/// the sbe_xip_decode_toc() and sbe_xip_find() APIs. This structure is +/// always returned with data elements in host-endian format. +/// +/// In the event that the TOC has been removed from the image, this structure +/// will also be returned by sbe_xip_find() with information populated from +/// the .fixed_toc section if possible. In this case the field \a iv_partial +/// will be set and only the fields \a iv_address, \a iv_imageData, \a iv_type +/// and \a iv_elements will be populated (all other fields will be set to 0). +/// +/// \note Only special-purpose applications will ever need to use this +/// structure given that the higher-level APIs sbe_xip_get_*() and +/// sbe_xip_set_*() are provided and should be used if possible, especially +/// given that the information may be truncated as described above. + +typedef struct { + + /// A pointer to the associated TOC entry as it exists in the image + /// + /// If \a iv_partial is set this field is returned as 0. + SbeXipToc* iv_toc; + + /// The full relocatable PORE address + /// + /// All relocatable addresses are computed from the \a iv_linkAddress + /// stored in the header. For scalar and string data, this is the + /// relocatable address of the data. For address-only entries, this is + /// the indexed address itself. + uint64_t iv_address; + + /// A host pointer to the first byte of text or data within the image + /// + /// For scalar or string types this is a host pointer to the first byte of + /// the data. For code pointers (addresses) this is host pointer to the + /// first byte of code. Note that any use of this field requires the + /// caller to handle conversion of the data to host endian-ness if + /// required. Only 8-bit and string data can be used directly on all + /// hosts. + void* iv_imageData; + + /// The item name + /// + /// This is a pointer in host memory to a string that names the TOC entry + /// requested. This field is set to a pointer to the ID string of the TOC + /// entry inside the image. If \a iv_partial is set this field is returned + /// as 0. + char* iv_id; + + /// The data type, one of the SBE_XIP_* constants + uint8_t iv_type; + + /// The number of elements in a vector + /// + /// This field is set from the TOC entry when the TOC entry is + /// decoded. This value is stored as 1 for scalar declarations, and may be + /// set to 0 for vectors with large or undeclared sizes. Otherwise it is + /// used to bounds check indexed accesses. + uint8_t iv_elements; + + /// Is this record only partially populated? + /// + /// This field is set to 0 normally, and only set to 1 if a lookup is made + /// in an image that only has the fixed TOC and the requested Id hashes to + /// the fixed TOC. + uint8_t iv_partial; + +} SbeXipItem; + + +/// Prototype entry in the .halt section +/// +/// The .halt section is generated by the 'reqhalt' macro. This structure +/// associates the address of each halt with the string form of the FAPI +/// return code associated with the halt. The string form is used because the +/// FAPI error return code is not constant. The .halt section is 4-byte +/// aligned, and each address/string entry is always padded to a multiple of 4 +/// bytes. +/// +/// In the .halt section the \a iv_string may be any length, thus the size of +/// each actual record is variable (although guaranteed to always be a +/// multiple of 4 bytes). Although the C compiler might natuarlly align +/// instances of this structure on a 64-bit boundary, the APIs that allow +/// access to the .halt section assume that the underlying machine can do +/// non-aligned loads from a pointer to this structure. + +typedef struct { + + /// The 64-bit relocatable address of the halt + /// + /// This is the address found in the PC (Status Register bits 16:63) when + /// the PORE halts. The full 64-bit form is used rather than the simple + /// 32-bit offset to support merging SEEPROM and PIBMEM .halt sections in + /// the SEEPROM IPL images. + uint64_t iv_address; + + /// A C-prototype for a variable-length 0-terminated ASCII string + /// + /// This is a prototype only to simplify C programming. The actual string + /// may be any length. + char iv_string[4]; + +} SbeXipHalt; + + +/// Validate an SBE-XIP image +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. +/// +/// \param[in] i_size The putative size of the image +/// +/// This API should be called first by all applications that manipulate +/// SBE-XIP images in host memory. The magic number is validated, and +/// the image is checked for consistency of the section table and table of +/// contents. The \a iv_imageSize field of the header must also match the +/// provided \a i_size parameter. Validation does not modify the image. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_validate(void* i_image, const uint32_t i_size); + + +/// Normalize the SBE-XIP image +/// +/// \param[in] io_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. +/// +/// SBE-XIP images must be normalized before any other APIs are allowed to +/// operate on the image. Since normalization modifies the image, an explicit +/// call to normalize the image is required. Briefly, normalization modifies +/// the TOC entries created by the final link to simplify search, updates, +/// modification and relocation of the image. Normalization is explained in +/// the written documentation of the SBE-XIP binary format. Normalization does +/// not modify the size of the image. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_normalize(void* io_image); + + +/// Return the size of an SBE-XIP image from the image header +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. +/// +/// \param[out] o_size A pointer to a variable returned as the size of the +/// image in bytes, as recorded in the image header. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_image_size(void* i_image, uint32_t* o_size); + + +/// Locate a section table entry and translate into host format +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. +/// +/// \param[in] i_sectionId Identifies the section to be queried. See \ref +/// sbe_xip_sections. +/// +/// \param[out] o_hostSection Updated to contain the section table entry +/// translated to host byte order. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_get_section(const void* i_image, + const int i_sectionId, + SbeXipSection* o_hostSection); + + +/// Endian translation of an SbeXipHeader object +/// +/// \param[out] o_hostHeader The destination object. +/// +/// \param[in] i_imageHeader The source object. +/// +/// Translation of a SbeXipHeader includes translation of all data members +/// including traslation of the embedded section table. This translation +/// works even if \a o_src == \a o_dest, i.e., in the destructive case. +void +sbe_xip_translate_header(SbeXipHeader* o_hostHeader, + const SbeXipHeader* i_imageHeader); + + +/// Get scalar data from an SBE-XIP image +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. The image is +/// also required to have been normalized. +/// +/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item +/// requested. +/// +/// \param[out] o_data A pointer to an 8-byte integer to receive the scalar +/// data. Assuming the item is located this variable is assigned by the call. +/// In the event of an error the final state of \a o_data is not specified. +/// +/// This API searches the SBE-XIP Table of Contents (TOC) for the item named +/// \a i_id, assigning \a o_data from the image if the item is found and is a +/// scalar value. Scalar values include 8- 32- and 64-bit integers and PORE +/// addresses. Image data smaller than 64 bits are extracted as unsigned +/// types, and it is the caller's responsibility to cast or convert the +/// returned data as appropriate. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_get_scalar(void *i_image, const char* i_id, uint64_t* o_data); + + +/// Get an integral element from a vector held in an SBE-XIP image +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. The image is +/// also required to have been normalized. +/// +/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item +/// requested. +/// +/// \param[in] i_index The index of the vector element to return. +/// +/// \param[out] o_data A pointer to an 8-byte integer to receive the +/// data. Assuming the item is located this variable is assigned by the call. +/// In the event of an error the final state of \a o_data is not specified. +/// +/// This API searches the SBE-XIP Table of Contents (TOC) for the \a i_index +/// element of the item named \a i_id, assigning \a o_data from the image if +/// the item is found, is a vector of an integral type, and the \a i_index is +/// in bounds. Vector elements smaller than 64 bits are extracted as unsigned +/// types, and it is the caller's responsibility to cast or convert the +/// returned data as appropriate. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_get_element(void *i_image, + const char* i_id, + const uint32_t i_index, + uint64_t* o_data); + + +/// Get string data from an SBE-XIP image +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. The image is +/// also required to have been normalized. +/// +/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item +/// requested. +/// +/// \param[out] o_data A pointer to a character pointer. Assuming the +/// item is located this variable is assigned by the call to point to the +/// string as it exists in the \a i_image. In the event of an error the final +/// state of \a o_data is not specified. +/// +/// This API searches the SBE-XIP Table of Contents (TOC) for the item named +/// \a i_id, assigning \a o_data if the item is found and is a string. It is +/// the caller's responsibility to copy the string from the \a i_image memory +/// space if necessary. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_get_string(void *i_image, const char* i_id, char** o_data); + + +/// Directly read 64-bit data from the image based on a PORE address +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. +/// +/// \param[in] i_poreAddress A relocatable PORE address contained in the +/// image, presumably of an 8-byte data area. The \a i_poreAddress is +/// required to be 8-byte aligned, otherwise the SBE_XIP_ALIGNMENT_ERROR code +/// is returned. +/// +/// \param[out] o_data The 64 bit data in host format that was found at \a +/// i_poreAddress. +/// +/// This API is provided for applications that need to manipulate SBE-XIP +/// images in terms of their relocatable PORE addresses. The API checks that +/// the \a i_poreAddress is properly aligned and contained in the image, then +/// reads the contents of \a i_poreAddress into \a o_data, performing +/// image-to-host endianess conversion if required. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_read_uint64(const void *i_image, + const uint64_t i_poreAddress, + uint64_t* o_data); + + +/// Set scalar data in an SBE-XIP image +/// +/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory. +/// The image is assumed to be consistent with the information contained in +/// the header regarding the presence of and sizes of all sections. The image +/// is also required to have been normalized. +/// +/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item +/// to be modified. +/// +/// \param[in] i_data The new scalar data. +/// +/// This API searches the SBE-XIP Table of Contents (TOC) for the item named +/// by \a i_id, updating the image from \a i_data if the item is found, has +/// a scalar type and can be modified. For this API the scalar types include +/// 8- 32- and 64-bit integers. Although PORE addresses are considered a +/// scalar type for sbe_xip_get_scalar(), PORE addresses can not be modified +/// by this API. The caller is responsible for ensuring that the \a i_data is +/// of the correct size for the underlying data element in the image. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_set_scalar(void* io_image, const char* i_id, const uint64_t i_data); + + +/// Set an integral element in a vector held in an SBE-XIP image +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. The image is +/// also required to have been normalized. +/// +/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item +/// to be updated. +/// +/// \param[in] i_index The index of the vector element to update. +/// +/// \param[out] i_data The new vector element. +/// +/// This API searches the SBE-XIP Table of Contents (TOC) for the \a i_index +/// element of the item named \a i_id, update the image from \a i_data if the +/// item is found, is a vector of an integral type, and the \a i_index is in +/// bounds. The caller is responsible for ensuring that the \a i_data is of +/// the correct size for the underlying data element in the image. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_set_element(void *i_image, + const char* i_id, + const uint32_t i_index, + const uint64_t i_data); + + +/// Set string data in an SBE-XIP image +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. The image is +/// also required to have been normalized. +/// +/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item +/// to be modified. +/// +/// \param[in] i_data A pointer to the new string data. +/// +/// This API searches the SBE-XIP Table of Contents (TOC) for the item named +/// \a i_id, which must be a string variable. If found, then the string data +/// in the image is overwritten with \a i_data. Strings are held 0-terminated +/// in the image, and the SBE-XIP format does not maintain a record of the +/// amount of memory allocated for an individual string. If a string is +/// overwritten by a shorter string then the 'excess' storage is effectively +/// lost. If the length of \a i_data is longer that the current strlen() of +/// the string data then \a i_data is silently truncated to the first +/// strlen(old_string) characters. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_set_string(void *io_image, const char* i_id, const char* i_data); + + +/// Directly write 64-bit data into the image based on a PORE address +/// +/// \param[in, out] io_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. +/// +/// \param[in] i_poreAddress A relocatable PORE address contained in the +/// image, presumably of an 8-byte data area. The \a i_poreAddress is +/// required to be 8-byte aligned, otherwise the SBE_XIP_ALIGNMENT_ERROR code +/// is returned. +/// +/// \param[in] i_data The 64 bit data in host format to be written to \a +/// i_poreAddress. +/// +/// This API is provided for applications that need to manipulate SBE-XIP +/// images in terms of their relocatable PORE addresses. The API checks that +/// the \a i_poreAddress is properly aligned and contained in the image, then +/// updates the contents of \a i_poreAddress with \a i_data, performing +/// host-to-image endianess conversion if required. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_write_uint64(void *io_image, + const uint64_t i_poreAddress, + const uint64_t i_data); + + +/// Map over an SBE-XIP image Table of Contents +/// +/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. The image is +/// also required to have been normalized. +/// +/// \param[in] i_fn A pointer to a function to call on each TOC entry. The +/// function has the prototype: +/// +/// \code +/// int (*i_fn)(void* io_image, +/// const SbeXipItem* i_item, +/// void* io_arg) +/// \endcode +/// +/// \param[in,out] io_arg The private argument of \a i_fn. +/// +/// This API iterates over each entry of the TOC, calling \a i_fn with +/// pointers to the image, an SbeXipItem* pointer, and a private argument. The +/// iteration terminates either when all TOC entries have been mapped, or \a +/// i_fn returns a non-zero code. +/// +/// \retval 0 Success; All TOC entries were mapped, including the case that +/// the .toc section is empty. +/// +/// \revtal non-0 May be either one of the SBE-XIP image error codes (see \ref +/// sbe_xip_image_errors), or a non-zero code from \a i_fn. Since the standard +/// SBE_XIP return codes are > 0, application-defined codes should be < 0. +int +sbe_xip_map_toc(void* io_image, + int (*i_fn)(void* io_image, + const SbeXipItem* i_item, + void* io_arg), + void* io_arg); + + +/// Find an SBE-XIP TOC entry +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. The image is +/// also required to have been normalized. +/// +/// \param[in] i_id A 0-byte terminated ASCII string naming the item to be +/// searched for. +/// +/// \param[out] o_item If the search is successful, then the object +/// pointed to by \a o_item is filled in with the decoded form of the +/// TOC entry for \a i_id. If the API returns a non-0 error code then the +/// final state of the storage at \a o_item is undefined. This parameter may +/// be suppied as 0, in which case sbe_xip_find() serves as a simple predicate +/// on whether an item is indexded in the TOC. +/// +/// This API searches the TOC of a normalized SBE-XIP image for the item named +/// \a i_id, and if found, fills in the structure pointed to by \a +/// o_item with a decoded form of the TOC entry. If the item is not found, +/// the following two return codes may be considered non-error codes: +/// +/// - SBE_XIP_ITEM_NOT_FOUND : No TOC record for \a i_id was found. +/// +/// - SBE_XIP_DATA_NOT_PRESENT : The item appears in the TOC, however the +/// section containing the data is no longer present in the image. +/// +/// If the TOC section has been deleted from the image, then the search is +/// restricted to the abbreviated TOC that indexes data in the .fixed section. +/// In this case the \a o_item structure is marked with a 1 in the \a +/// iv_partial field since the abbreviated TOC can not populate the entire +/// SbeXipItem structure. +/// +/// \note This API should typically only be used as a predicate, not as a way +/// to access the image via the returned SbeXipItem structure. To obtain data +/// from the image or update data in the image use the sbe_xip_get_*() and +/// sbe_xip_set_*() APIs respectively. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_find(void* i_image, + const char* i_id, + SbeXipItem* o_item); + + +/// Map over an SBE-XIP image .halt section +/// +/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. +/// +/// \param[in] i_fn A pointer to a function to call on each entry in .halt. +/// The function has the prototype: +/// +/// \code +/// int (*i_fn)(void* io_image, +/// const uint64_t i_poreAddress, +/// const char* i_rcString, +/// void* io_arg) +/// +/// \param[in,out] io_arg The private argument of \a i_fn. +/// +/// This API iterates over each entry of the .halt section, calling \a i_fn +/// with each HALT address, the string form of the return code associated with +/// that HALT address, and a private argument. The iteration terminates either +/// when all .halt entries have been mapped, or \a i_fn returns a non-zero +/// code. The \a i_poreAddddress passed to \a i_fn is the full 48-bit +/// relocatable PORE address. +/// +/// \retval 0 Success, including the case that the image has no .halt section. +/// +/// \revtal non-0 May be either one of the SBE-XIP image error codes (see \ref +/// sbe_xip_image_errors), or any non-zero code from \a i_fn. Since the +/// standard SBE_XIP return codes are > 0, application-defined codes should be +/// < 0. +int +sbe_xip_map_halt(void* io_image, + int (*i_fn)(void* io_image, + const uint64_t i_poreAddress, + const char* i_rcString, + void* io_arg), + void* io_arg); + + +/// Get the string from of a HALT code from an SBE-XIP image .halt section +/// +/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. +/// +/// \param[in] i_poreAddress This is the 48-bit address found in the PC when +/// the PORE halts. This address is actually 4 bytes beyond the actual HALT +/// instruction, however for simplicity this is the address used to index the +/// HALT. +/// +/// \param[out] o_rcString The caller provides the address of a string-pointer +/// variable which is updated with a pointer to the string form of the halt +/// code associated with \a i_poreAddress (assuming a successful completion). +/// +/// \retval 0 Success +/// +/// \retval SBE_XIP_ITEM_NOT_FOUND The \a i_poreAddress is not associated +/// with a halt code in .halt. +/// +/// \revtal Other See \ref sbe_xip_image_errors +int +sbe_xip_get_halt(void* io_image, + const uint64_t i_poreAdress, + const char** o_rcString); + + +/// Delete a section from an SBE-XIP image in host memory +/// +/// \param[in,out] i_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. The image is +/// also required to have been normalized. +/// +/// \param[in] i_sectionId Identifies the section to be deleted. See \ref +/// sbe_xip_sections. +/// +/// This API effectively deletes a section from an SBE-XIP image held in host +/// memory. Unless the requested section \a i_section is already empty, only +/// the final (highest address offset) section of the image may be deleted. +/// Deleting the final section of the image means that the section size is set +/// to 0, and the size of the image recorded in the header is reduced by the +/// section size. This API does not check for or warn if other sections in +/// the image reference the deleted section. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_delete_section(void* io_image, const int i_sectionId); + + +/// Duplicate a section from an SBE-XIP image in host memory +/// +/// \param[in,out] i_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. +/// +/// \param[in] i_sectionId Identifies the section to be duplicated. See \ref +/// sbe_xip_sections. +/// +/// \param[out] o_duplicate At exit, points to the newly allocated and +/// initialized duplicate of the given section. The caller is responsible for +/// free()-ing this memory when no longer required. +/// +/// \param[out] o_size At exit, contains the size (in bytes) of the duplicated +/// section. +/// +/// This API creates a bytewise duplicate of a non-empty section into newly +/// malloc()-ed memory. At exit \a o_duplicate points to the duplicate, and \i +/// o_size is set the the size of the duplicated section. The caller is +/// responsible for free()-ing the memory when no longer required. The +/// pointer at \o_duplicate is set to NULL (0) and teh \a o_size is set to 0 +/// in the event of any failure. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_duplicate_section(const void* i_image, + const int i_sectionId, + void** o_duplicate, + uint32_t* size); + + +/// Append binary data to an SBE-XIP image held in host memory +/// +/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory. The +/// image is assumed to be consistent with the information contained in the +/// header regarding the presence of and sizes of all sections. The image is +/// also required to have been normalized. +/// +/// \param[in] i_sectionId Identifies the section to contain the new data. +/// +/// \param[in] i_data A pointer to the data to be appended to the image. If +/// this pointer is NULL (0), then the effect is as if \a i_data were a +/// pointer to an \a i_size array of 0 bytes. +/// +/// \param[in] i_size The size of the data to be appended in bytes. If \a +/// i_data is 0, then this is the number of bytes to clear. +/// +/// \param[in] i_allocation The size of the memory region containing the +/// image, measured from the first byte of the image. The call will fail if +/// appending the new data plus any alignment padding would overflow the +/// allocated memory. +/// +/// \param[out] o_sectionOffset If non-0 at entry, then the API updates the +/// location pointed to by \a o_sectionOffset with the offset of the first +/// byte of the appended data within the indicated section. +/// +/// This API copies data from \a i_data to the end of the indicated \a +/// i_section. The section \a i_section must either be empty, or must be the +/// final (highest address) section in the image. If the section is initially +/// empty and \a i_size is non-0 then the section is created at the end of the +/// image. The size of \a i_section and the size of the image are always +/// adjusted to reflect the newly added data. This is a simple binary copy +/// without any interpretation (e.g., endian-translation) of the copied data. +/// The caller is responsible for insuring that the host memory area +/// containing the SBE-XIP image is large enough to hold the newly appended +/// data without causing addressing errors or buffer overrun errors. +/// +/// The final parameter \a o_sectionOffset is optional, and may be passed as +/// NULL (0) if the application does not require the information. This return +/// value is provided to simplify typical use cases of this API: +/// +/// - A scan program is appended to the image, or a run-time data area is +/// allocated and cleared at the end of the image. +/// +/// - Pointer variables in the image are updated with PORE addresses obtained +/// via sbe_xip_section2pore(), or +/// other procedure code initializes a newly allocated and cleared data area +/// via host addresses obtained from sbe_xip_section2host(). +/// +/// Regarding alignment, note that the SBE-XIP format requires that sections +/// maintain an initial alignment that varies by section, and the API will +/// enforce these alignment constraints for all sections created by the API. +/// All alignment is relative to the first byte of the image (\a io_image) - +/// \e not to the current in-memory address of the image. By specification +/// SBE-XIP images must be loaded at a 4K alignment in order for PORE hardware +/// relocation to work, however the APIs don't require this 4K alignment for +/// in-memory manipulation of images. Images to be executed on PoreVe will +/// normally require at least 8-byte final aligment in order to guarantee that +/// the PoreVe can execute an 8-byte fetch or load/store of the final +/// doubleword. +/// +/// \note If the TOC section is modified then the image is marked as having an +/// unsorted TOC. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_append(void* io_image, + const int i_sectionId, + const void* i_data, + const uint32_t i_size, + const uint32_t i_allocation, + uint32_t* o_sectionOffset); + + +/// Convert an SBE-XIP section offset to a relocatable PORE address +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory +/// +/// \param[in] i_sectionId A valid SBE-XIP section identifier; The section +/// must be non-empty. +/// +/// \param[in] i_offset An offset (in bytes) within the section. At least one +/// byte at \a i_offset must be currently allocated in the section. +/// +/// \param[in] o_poreAddress The equivalent relocatable PORE address is +/// returned via this pointer. Since valid PORE addresses are always either +/// 4-byte (code) or 8-byte (data) aligned, this API checks the aligment of +/// the translated address and returns SBE_XIP_ALIGNMENT_ERROR if the PORE +/// address is not at least 4-byte aligned. Note that the translated address +/// is still returned even if incorrectly aligned. +/// +/// This API is typically used to translate section offsets returned from +/// sbe_xip_append() into relocatable PORE addresses. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_section2pore(const void* i_image, + const int i_sectionId, + const uint32_t i_offset, + uint64_t* o_poreAddress); + + +/// Convert an SBE-XIP relocatable PORE address to a host memory address +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. +/// +/// \param[in] i_poreAddress A relocatable PORE address putatively addressing +/// relocatable memory contained in the image. +/// +/// \param[out] o_hostAddress The API updates the location pointed to by \a +/// o_hostAddress with the host address of the memory addressed by \a +/// i_poreAddress. In the event of an error (non-0 return code) the final +/// content of \a o_hostAddress is undefined. +/// +/// This API is typically used to translate relocatable PORE addresses stored +/// in the SBE-XIP image into the equivalent host address of the in-memory +/// image, allowing host-code to manipulate arbitrary data structures in the +/// image. If the \a i_poreAddress does not refer to memory within the image +/// (as determined by the link address and image size) then the +/// SBE_XIP_INVALID_ARGUMENT error code is returned. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_pore2host(const void* i_image, + const uint64_t i_poreAddress, + void** o_hostAddress); + + +/// Convert an SBE-XIP relocatable PORE address to section Id and offset +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory. +/// +/// \param[in] i_poreAddress A relocatable PORE address putatively addressing +/// relocatable memory contained in the image. +/// +/// \param[out] o_section The API updates the location pointed to by \a +/// o_section with the section Id of the memory addressed by \a +/// i_poreAddress. In the event of an error (non-0 return code) the final +/// content of \a o_section is undefined. +/// +/// \param[out] o_offset The API updates the location pointed to by \a +/// o_offset with the byte offset of the memory addressed by \a i_poreAddress +/// within \a o_section. In the event of an error (non-0 return code) the +/// final content of \a o_offset is undefined. +/// +/// This API is typically used to translate relocatable PORE addresses stored +/// in the SBE-XIP image into the equivalent section + offset form, allowing +/// host-code to manipulate arbitrary data structures in the image. If the \a +/// i_poreAddress does not refer to memory within the image (as determined by +/// the link address and image size) then the SBE_XIP_INVALID_ARGUMENT error +/// code is returned. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_pore2section(const void* i_image, + const uint64_t i_poreAddress, + int* o_section, + uint32_t* o_offset); + + +/// Convert an in-memory SBE-XIP host address to a relocatable PORE address +/// +/// \param[in] i_image A pointer to an SBE-XIP image in host memory +/// +/// \param[in] i_hostAddress A host address addressing data within the image. +/// +/// \param[out] o_poreAddress The API updates the location pointed to by \a +/// o_poreAddress with the equivelent relocatable PORE address of the memory +/// addressed by i_hostAddress. Since valid PORE addresses are always either +/// 4-byte (code) or 8-byte (data) aligned, this API checks the aligment of +/// the translated address and returns SBE_XIP_ALIGNMENT_ERROR if the PORE +/// address is not at least 4-byte aligned. Note that the translated address +/// is still returned evn if incorrectly aligned. +/// +/// This API is provided as a convenient way to convert host memory addresses +/// for an in-memory SBE-XIP image into PORE addresses correctly relocated for +/// the image, for example to update pointer variables in the image. If the +/// \a i_hostAddress does not refer to memory within the image (as determined +/// by the image address and image size) then the SBE_XIP_INVALID_ARGUMENT +/// error code is returned. +/// +/// \retval 0 Success +/// +/// \retval non-0 See \ref sbe_xip_image_errors +int +sbe_xip_host2pore(const void* i_image, + void* i_hostAddress, + uint64_t* i_poreAddress); + + +/// \defgroup sbe_xip_image_errors Error codes from SBE-XIP image APIs +/// +/// @{ + +/// A putative SBE-XIP image does not have the correct magic number, or +/// contains some other major inconsistency. +#define SBE_XIP_IMAGE_ERROR 1 + +/// The TOC may be missing, partially present or may have an alignment problem. +#define SBE_XIP_TOC_ERROR 2 + +/// A named item was not found in the SBE-XIP TOC, or a putative HALT address +/// is not associated with a halt code in .halt. +#define SBE_XIP_ITEM_NOT_FOUND 3 + +/// A named item appears in the SBE-XIP TOC, but the data is not present in +/// the image. This error can occur if sections have been deleted from the +/// image. +#define SBE_XIP_DATA_NOT_PRESENT 4 + +/// A named item appears in the SBE-XIP TOC, but the data can not be +/// modified. This error will occur if an attempt is made to modify an +/// address-only entry. +#define SBE_XIP_CANT_MODIFY 5 + +/// A direct or implied argument is invalid, e.g. an illegal data type or +/// section identifier, or an address not contained within the image. +#define SBE_XIP_INVALID_ARGUMENT 6 + +/// A data type mismatch or an illegal type was specified or implied for an +/// operation. +#define SBE_XIP_TYPE_ERROR 7 + +/// A bug in an SBE-XIP image API +#define SBE_XIP_BUG 8 + +/// The image must first be normalized with sbe_xip_normalize(). +#define SBE_XIP_NOT_NORMALIZED 9 + +/// Attempt to delete a non-empty section that is not the final section of the +/// image, or an attempt to append data to a non-empty section that is not the +/// final section of the image, or an attempt to operate on an empty section +/// for those APIs that prohibit this. +#define SBE_XIP_SECTION_ERROR 10 + +/// An address translation API returned a PORE address that was not at least +/// 4-byte aligned, or alignment violations were observed by +/// sbe_xip_validate() or sbe_xip_append(). +#define SBE_XIP_ALIGNMENT_ERROR 11 + +/// An API that performs dynamic memory allocation was unable to allocate +/// memory. +#define SBE_XIP_NO_MEMORY 12 + +/// Attempt to get or set a vector element with an index that is outside of +/// the declared bounds of the vector. +#define SBE_XIP_BOUNDS_ERROR 13 + +/// Attempt to grow the image past its defined memory allocation +#define SBE_XIP_WOULD_OVERFLOW 14 + +/// Error associated with the disassembler occured. +#define SBE_XIP_DISASSEMBLER_ERROR 15 + +/// hash collision creating the .fixed_toc section +#define SBE_XIP_HASH_COLLISION 16 + +/// Applications can expand this macro to declare an array of string forms of +/// the error codes if desired. +#define SBE_XIP_ERROR_STRINGS(var) \ + const char* var[] = { \ + "Success", \ + "SBE_XIP_IMAGE_ERROR", \ + "SBE_XIP_TOC_ERROR", \ + "SBE_XIP_ITEM_NOT_FOUND", \ + "SBE_XIP_DATA_NOT_PRESENT", \ + "SBE_XIP_CANT_MODIFY", \ + "SBE_XIP_INVALID_ARGUMENT", \ + "SBE_XIP_TYPE_ERROR", \ + "SBE_XIP_BUG", \ + "SBE_XIP_NOT_NORMALIZED", \ + "SBE_XIP_SECTION_ERROR", \ + "SBE_XIP_ALIGNMENT_ERROR", \ + "SBE_XIP_NO_MEMORY", \ + "SBE_XIP_BOUNDS_ERROR", \ + "SBE_XIP_WOULD_OVERFLOW", \ + "SBE_XIP_DISASSEMBLER_ERROR", \ + "SBE_XIP_HASH_COLLISION", \ + } + +/// Applications can use this macro to safely index the array of error +/// strings. +#define SBE_XIP_ERROR_STRING(var, n) \ + ((((n) < 0) || ((n) > (int)(sizeof(var) / sizeof(char*)))) ? \ + "Bug : Invalid SBE-XIP error code" : var[n]) + +/// @} + +/// Disassembler error codes. +#define DIS_IMAGE_ERROR 1 +#define DIS_MEMORY_ERROR 2 +#define DIS_DISASM_ERROR 3 +#define DIS_RING_NAME_ADDR_MATCH_SUCCESS 4 +#define DIS_RING_NAME_ADDR_MATCH_FAILURE 5 +#define DIS_TOO_MANY_DISASM_WARNINGS 6 +#define DIS_DISASM_TROUBLES 7 + +#define DIS_ERROR_STRINGS(var) \ + const char* var[] = { \ + "Success", \ + "DIS_IMAGE_ERROR", \ + "DIS_MEMORY_ERROR", \ + "DIS_DISASM_ERROR", \ + "DIS_RING_NAME_ADDR_MATCH_SUCCESS", \ + "DIS_RING_NAME_ADDR_MATCH_FAILURE", \ + "DIS_TOO_MANY_DISASM_WARNINGS", \ + "DIS_DISASM_TROUBLES", \ + } + +#define DIS_ERROR_STRING(var, n) \ + ((((n) < 0) || ((n) > (int)(sizeof(var) / sizeof(char*)))) ? \ + "Bug : Invalid DIS error code" : var[n]) + +#if 0 +{ /* So __cplusplus doesn't mess w/auto-indent */ +#endif +#ifdef __cplusplus +} +#endif + +#endif // __ASSEMBLER__ + + +//////////////////////////////////////////////////////////////////////////// +// Assembler Definitions +//////////////////////////////////////////////////////////////////////////// + +#ifdef __ASSEMBLER__ + +/// Create an XIP TOC entry +/// +/// \param[in] index The string form of the \a index symbol is created and +/// linked from the TOC entry to allow external search procedures to locate +/// the \a address. +/// +/// \param[in] type One of the SBE_XIP_* type constants; See \ref +/// sbe_xip_toc_types. +/// +/// \param[in] address The address of the idexed code or data; This wlll +/// typically be a symbol. +/// +/// \param[in] elements <Optional> For vector types, number of elements in the +/// vector, which is limited to an 8-bit unsigned integer. This parameter +/// defaults to 1 which indicates a scalar type. Declaring a vector with 0 +/// elements disables bounds checking on vector accesses, and can be used if +/// very large or indeterminate sized vectors are required. The TOC format +/// does not support vectors of strings or addresses. +/// +/// The \c .xip_toc macro creates a XIP Table of Contents (TOC) structure in +/// the \c .toc section, as specified by the parameters. This macro is +/// typically not used directly in assembly code. Instead programmers should +/// use .xip_quad, .xip_quada, .xip_quadia, .xip_address, .xip_string or +/// .xip_cvs_revision. + + .macro .xip_toc, index:req, type:req, address:req, elements=1 + + .if (((\type) < 1) || ((\type) > SBE_XIP_MAX_TYPE_INDEX)) + .error ".xip_toc : Illegal type index" + .endif + + // First push into the .strings section to lay down the + // string form of the index name under a local label. + + .pushsection .strings +7667862: + .asciz "\index" + .popsection + + // Now the 12-byte TOC entry is created. Push into the .toc section + // and lay down the first 4 bytes which are always a pointer to the + // string just declared. The next 4 bytes are the address of the data + // (or the address itself in the case of address types). The final 4 + // bytes are the type, section (always 0 prior to normalization), + // number of elements, and a padding byte. + + .pushsection .toc + + .long 7667862b, (\address) + .byte (\type), 0, (\elements), 0 + + .popsection + + .endm + + +/// Allocate and initialize 64-bit global scalar or vector data and create the +/// TOC entry. +/// +/// \param[in] symbol The name of the scalar or vector; this name is also used +/// as the TOC index of the data. +/// +/// \param[in] init The initial value of (each element of) the data. +/// This is a 64-bit integer; To allocate address pointers use .xip_quada. +/// +/// \param[in] elements The number of 64-bit elements in the data structure, +/// defaulting to 1, with a maximum value of 255. +/// +/// \param[in] section The section where the data will be allocated, +/// default depends on the memory space + + .macro .xip_quad, symbol:req, init:req, elements=1, section + + ..xip_quad_helper .quad, \symbol, (\init), (\elements), \section + + .endm + + +/// Allocate and initialize 64-bit global scalar or vector data containing a +/// relocatable address in and create the TOC entry. +/// +/// \param[in] symbol The name of the scalar or vector; this name is also used +/// as the TOC index of the data. +/// +/// \param[in] init The initial value of (each element of) the data. This +/// will typically be a symbolic address. If the intention is to define an +/// address that will always be filled in later by image manipulation tools, +/// then use the .xip_quad macro with a 0 initial value. +/// +/// \param[in] elements The number of 64-bit elements in the data structure, +/// defaulting to 1, with a maximum value of 255. +/// +/// \param[in] section The section where the data will be allocated, +/// default depends on the memory space + + .macro .xip_quada, symbol:req, offset:req, elements=1, section + + ..xip_quad_helper .quada, \symbol, (\offset), (\elements), \section + + .endm + + +/// Helper for .xip_quad and .xip_quada + + .macro ..xip_quad_helper, directive, symbol, init, elements, section + + .if (((\elements) < 1) || ((\elements) > 255)) + .error "The number of vector elements must be in the range 1..255" + .endif + + ..xip_pushsection \section + .balign 8 + + .global \symbol +\symbol\(): + .rept (\elements) + \directive (\init) + .endr + + .popsection + + .xip_toc \symbol, SBE_XIP_UINT64, \symbol, (\elements) + + .endm + + +/// Allocate and initialize 64-bit global scalar or vector data containing +/// full 64-bit addresses and create a TOC entry +/// +/// \param[in] symbol The name of the scalar or vector; this name is also used +/// as the TOC index of the data. +/// +/// \param[in] space A valid PORE memory space descriptor +/// +/// \param[in] offset A 32-bit relocatable offset +/// +/// \param[in] elements The number of 64-bit elements in the data structure, +/// defaulting to 1, with a maximum value of 255. +/// +/// \param[in] section The section where the data will be allocated, +/// default depends on the memory space + + .macro .xip_quadia, symbol:req, space:req, offset:req, \ + elements=1, section + + .if (((\elements) < 1) || ((\elements) > 255)) + .error "The number of vector elements must be in the range 1..255" + .endif + + ..xip_pushsection \section + .balign 8 + + .global \symbol +\symbol\(): + .rept (\elements) + .quadia (\space), (\offset) + .endr + + .popsection + + .xip_toc \symbol, SBE_XIP_UINT64, \symbol, (\elements) + + .endm + +/// Default push into .ipl_data unless in an OCI space, then .data + + .macro ..xip_pushsection, section + + .ifnb \section + .pushsection \section + .else + .if (_PGAS_DEFAULT_SPACE == PORE_SPACE_OCI) + .pushsection .data + .else + .pushsection .ipl_data + .endif + .endif + + .balign 8 + + .endm + +/// Allocate and initialize a string in .strings +/// +/// \param[in] index The string will be stored in the TOC using this index +/// symbol. +/// +/// \param[in] string The string to be allocated in .strings. String space is +/// fixed once allocated. Strings designed to be overwritten by external tools +/// should be allocated to be as long as eventually needed (e.g., by a string +/// of blanks.) + + .macro .xip_string, index:req, string:req + + .pushsection .strings +7874647: + .asciz "\string" + .popsection + + .xip_toc \index, SBE_XIP_STRING, 7874647b + + .endm + + +/// Allocate and initialize a CVS Revison string in .strings +/// +/// \param[in] index The string will be stored in the TOC using this index +/// symbol. +/// +/// \param[in] string A CVS revision string to be allocated in .strings. CVS +/// revision strings are formatted by stripping out and only storing the +/// actual revision number : +/// +/// \code +/// "$Revision <n>.<m> $" -> "<n>.<m>" +/// \endcode + + + .macro .xip_cvs_revision, index:req, string:req + + .pushsection .strings +7874647: + ..cvs_revision_string "\string" + .popsection + + .xip_toc \index, SBE_XIP_STRING, 7874647b + + .endm + + +/// Shorthand to create a TOC entry for an address +/// +/// \param[in] index The symbol will be indexed as this name +/// +/// \param[in] symbol <Optional> The symbol to index; by default the same as +/// the index. + + .macro .xip_address, index:req, symbol + + .ifb \symbol + .xip_toc \index, SBE_XIP_ADDRESS, \index + .else + .xip_toc \index, SBE_XIP_ADDRESS, \symbol + .endif + + .endm + + +/// Edit and allocate a CVS revision string +/// +/// CVS revision strings are formatted by stripping out and only storing the +/// actual revision number : +/// \code +/// "$Revision <n>.<m> $" -> "<n>.<m>" +/// \endcode + + .macro ..cvs_revision_string, rev:req + .irpc c, \rev + .ifnc "\c", "$" + .ifnc "\c", "R" + .ifnc "\c", "e" + .ifnc "\c", "v" + .ifnc "\c", "i" + .ifnc "\c", "s" + .ifnc "\c", "i" + .ifnc "\c", "o" + .ifnc "\c", "n" + .ifnc "\c", ":" + .ifnc "\c", " " + .ascii "\c" + .endif + .endif + .endif + .endif + .endif + .endif + .endif + .endif + .endif + .endif + .endif + .endr + .byte 0 + .endm + +#endif // __ASSEMBLER__ + +#endif // __SBE_XIP_TOC_H diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_delta_scan_rw.h b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_delta_scan_rw.h index 6cdf89108..a0466c2ef 100644 --- a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_delta_scan_rw.h +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_delta_scan_rw.h @@ -22,16 +22,22 @@ * IBM_PROLOG_END_TAG */ //***** IMPORTANT - Assumptions (you may have to change these settings) ****** -#define ASM_RS4_LAUNCH_BUF_SIZE 24 // Byte size of binary RS4 launch buffer w/last two - // nops removed. -#define OVERRIDE_OFFSET 8 // Byte offset of forward pointer's addr relative - // to base forward pointer's addr. -#define SLW_MS_MAX_BUF_SIZE 50000000 // Max 50MB for SLW mainstore image. +#define ASM_RS4_LAUNCH_BUF_SIZE 24 // Byte size of binary RS4 launch buffer w/last two + // nops removed. Must always be 8-byte aligned. +#define OVERRIDE_OFFSET 8 // Byte offset of forward pointer's addr relative + // to base forward pointer's addr. +#define SIZE_IMAGE_BUF_MAX 50000000 // Max 50MB image buffer size. +#define SIZE_IMAGE_CENTAUR_MAX 5000000 // Max 5MB image buffer size. +#define SCOM_REG_MASK 0x00ffffff // Scom register mask (within a chiplet) +#define CID_MASK 0xff000000 // Chiplet ID mask +#define CID_EX_LOW 0x10 // Lowest EX chiplet addr +#define CID_EX_HIGH 0x1f // Highest EX chiplet addr + /***** Scan Control Regs *****/ #define P8_PORE_CLOCK_CONTROLLER_REG 0x00030007 // Addr of clock ctrl scom reg #define P8_PORE_SHIFT_REG 0x00038000 // Addr of scom reg that does scan ring shifting -#define P8_SCAN_CHECK_WORD 0xA5A55A5A // Header check word +#define P8_SCAN_CHECK_WORD 0xA5A55A5A // Header check word /***** Ring state *****/ #define MAX_RING_SIZE 1000000 // This is the max binary ring size in bits @@ -42,28 +48,44 @@ #define PRINT_WF_DIS // Causes wf inline code to be disassembled and written to file. /***** Return codes *****/ -#define DSLWB_RING_SEARCH_MATCH 0 -#define DSLWB_RING_SEARCH_EXHAUST_MATCH 30 -#define DSLWB_RING_SEARCH_NO_MATCH 31 -#define DSLWB_RING_SEARCH_MESS 32 -#define DSLWB_SLWB_SUCCESS 0 -#define DSLWB_SLWB_NO_RING_MATCH 40 -#define DSLWB_SLWB_DX_ERROR 41 -#define DSLWB_SLWB_WF_ERROR 42 -#define DSLWB_SLWB_WF_IMAGE_ERROR 43 -#define DSLWB_SLWB_IMAGE_ERROR 44 -#define DSLWB_SLWB_UNKNOWN_ERROR 45 -#define IMGBUILD_SUCCESS 0 // Successful image build. -#define IMGBUILD_ERR_MEMORY 20 // Memory allocation error. -#define IMGBUILD_ERR_XIP_MISC 25 // Miscellaneous XIP image error. -#define IMGBUILD_ERR_SECTION_DELETE 50 // Err assoc w/deleting ELF section. -#define IMGBUILD_ERR_APPEND 51 // Err assoc w/appending to ELF section. -#define IMGBUILD_ERR_INCOMPLETE_IMG_BUILD 52 // The image was built, but with errors. -#define IMGBUILD_ERR_FWD_BACK_PTR_MESS 53 // Forward or backward pointer mess. -#define IMGBUILD_ERR_KEYWORD_NOT_FOUND 54 // Image keyword not found. -#define IMGBUILD_ERR_MISALIGNED_RING_LAYOUT 55 // Ring layout is misaligned. -#define IMGBUILD_ERR_IMAGE_TOO_LARGE 56 // Image too large. Exceeded max size. -#define IMGBUILD_ERR_CHECK_CODE 60 // Coding problem - impossible state. +#define DSLWB_RING_SEARCH_MATCH 0 +#define DSLWB_RING_SEARCH_EXHAUST_MATCH 30 +#define DSLWB_RING_SEARCH_NO_MATCH 31 +#define DSLWB_RING_SEARCH_MESS 32 +#define DSLWB_SLWB_SUCCESS 0 +#define DSLWB_SLWB_NO_RING_MATCH 40 +#define DSLWB_SLWB_DX_ERROR 41 +#define DSLWB_SLWB_WF_ERROR 42 +#define DSLWB_SLWB_WF_IMAGE_ERROR 43 +#define DSLWB_SLWB_IMAGE_ERROR 44 +#define DSLWB_SLWB_UNKNOWN_ERROR 45 +#define IMGBUILD_SUCCESS 0 // Successful image build. +#define IMGBUILD_ERR_CHECK_CODE 2 // Coding problem. +#define IMGBUILD_ERR_MEMORY 4 // Memory allocation error. +#define IMGBUILD_INVALID_IMAGE 10 // Invalid image. +#define IMGBUILD_IMAGE_SIZE_MISMATCH 11 // Mismatch between image sizes. +#define IMGBUILD_ERR_PORE_INLINE_ASM 20 // Err assoc w/inline assembler. +#define IMGBUILD_ERR_SECTION_DELETE 50 // Err assoc w/deleting ELF section. +#define IMGBUILD_ERR_APPEND 51 // Err assoc w/appending to ELF section. +#define IMGBUILD_ERR_INCOMPLETE_IMG_BUILD 52 // The image was built, but with errors. +#define IMGBUILD_ERR_FWD_BACK_PTR_MESS 53 // Forward or backward pointer mess. +#define IMGBUILD_ERR_KEYWORD_NOT_FOUND 54 // Image keyword not found. +#define IMGBUILD_ERR_MISALIGNED_RING_LAYOUT 55 // Ring layout is misaligned. +#define IMGBUILD_ERR_IMAGE_TOO_LARGE 56 // Image too large. Exceeded max size. +#define IMGBUILD_ERR_XIP_MISC 57 // Miscellaneous XIP image error. +#define IMGBUILD_ERR_RS4_DECOMPRESS 58 // Error during RS4 decompression. +#define IMGBUILD_ERR_PORE_INLINE 60 // Pore inline error. +#define IMGBUILD_ERR_RAM_INVALID_PARM 65 // Invalid Ramming parameter. +#define IMGBUILD_ERR_RAM_TABLE_FAIL 66 // Unsuccessful RAM table build. +#define IMGBUILD_ERR_SCOM_INVALID_PARM 70 // Invalid Scomming parameter. +#define IMGBUILD_ERR_SCOM_HDRS_NOT_SYNCD 72 // Scom headers out of sync. +#define IMGBUILD_ERR_SCOM_ENTRY_NOT_FOUND 74 // Scom entry not found (OR/AND oper.) +#define IMGBUILD_ERR_SCOM_REPEAT_ENTRIES 76 // Repeat entries not allow. +#define IMGBUILD_ERR_SCOM_TABLE_FAIL 79 // Unsuccessful SCOM table build. + +#ifdef SLW_COMMAND_LINE_RAM +#define SLW_COMMAND_LINE +#endif #ifdef __FAPI #define MY_INF(_fmt_, _args_...) FAPI_INF(_fmt_, ##_args_) @@ -73,28 +95,42 @@ #define MY_ERR(_fmt_, _args_...) FAPI_INF(_fmt_, ##_args_) #endif // End of SLW_COMMAND_LINE #define MY_DBG(_fmt_, _args_...) FAPI_DBG(_fmt_, ##_args_) -#else +#else // End of __FAPI +#ifdef SLW_COMMAND_LINE #define MY_INF(_fmt_, _args_...) fprintf(stdout, _fmt_, ##_args_) #define MY_ERR(_fmt_, _args_...) fprintf(stderr, _fmt_, ##_args_) #define MY_DBG(_fmt_, _args_...) fprintf(stdout, _fmt_, ##_args_) -#endif // End of FAPI +#else // End of SLW_COMMAND_LINE +#define MY_INF(_fmt_, _args_...) +#define MY_ERR(_fmt_, _args_...) +#define MY_DBG(_fmt_, _args_...) +#endif // End of not(__FAPI) & not(SLW_COMMAND_LINE) +#endif #include <stdlib.h> #include <stdio.h> #include <string.h> + #ifdef SLW_COMMAND_LINE #include <sys/mman.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #endif //End of SLW_COMMAND_LINE + #ifndef SLW_BUILD_WF_P0_FIX #include "pore_bitmanip.H" #endif // SLW_BUILD_WF_P0_FIX -#include "p8_pore_api.h" -#include "p8_pore_static_data.h" + +//#include "p8_pore_api.h" +//#include "p8_pore_static_data.h" + +#ifndef SLW_COMMAND_LINE_RAM #include "p8_scan_compression.H" +#endif + #include "sbe_xip_image.h" + #undef __PORE_INLINE_ASSEMBLER_C__ #include "pore_inline.h" @@ -102,6 +138,9 @@ extern "C" { #endif + +#ifndef SLW_COMMAND_LINE_RAM + // Info: // DeltaRingLayout describes the sequential order of the content in the compressed delta // ring blocks in the .initf section in the SBE-XIP images. @@ -115,103 +154,114 @@ extern "C" { // - {rs4Delta} must start on a double-word bournday (see earlier rule how to do that). // typedef struct { - uint64_t entryOffset; - uint64_t backItemPtr; - uint32_t sizeOfThis; - uint32_t sizeOfMeta; // Exact size of meta data. Arbitrary size. Not null terminated. - uint32_t ddLevel; - uint8_t sysPhase; - uint8_t override; - uint8_t reserved1; - uint8_t reserved2; - char *metaData; // Arbitrary size. Extra bytes to next alignment are random or 0s. - uint32_t *rs4Launch; // Code. Must be 4-byte aligned. - uint32_t *rs4Delta; // Data. Must be 8-byte aligned. - uint32_t *wfInline; // Code. Must be 4-byte aligned. + uint64_t entryOffset; + uint64_t backItemPtr; + uint32_t sizeOfThis; + uint32_t sizeOfMeta; // Exact size of meta data. Arbitrary size. Not null terminated. + uint32_t ddLevel; + uint8_t sysPhase; + uint8_t override; + uint8_t reserved1; + uint8_t reserved2; + char *metaData; // Arbitrary size. Extra bytes to next alignment are random or 0s. + uint32_t *rs4Launch; // Code. Must be 4-byte aligned. Actually should be 8-B align! + uint32_t *rs4Delta; // Data. Must be 8-byte aligned. + uint32_t *wfInline; // Code. Must be 4-byte aligned. Actually should be 8-B align! } DeltaRingLayout; typedef struct { - uint32_t sizeOfData; - char data[]; + uint32_t sizeOfData; + char data[]; } MetaData; -int p8_ipl_build( void *i_imageIn, - uint32_t i_ddLevel, - void *i_imageOut, - uint32_t i_sizeImageOutMax); - -int get_ring_layout_from_image2( const void *i_imageIn, - uint32_t i_ddLevel, - uint8_t i_sysPhase, - DeltaRingLayout **o_rs4RingLayout, - void **nextRing); - -int write_ring_block_to_image( void *io_image, - DeltaRingLayout *i_ringBlock, - uint32_t i_sizeImageMax); - -int gen_ring_delta_state( - uint32_t bitLen, - uint32_t *i_init, - uint32_t *i_alter, - uint32_t *o_delta, - uint32_t verbose); - -int write_delta_ring_to_image( - char *i_fnImage, - CompressedScanData *i_RS4, - uint32_t i_ddLevel, - uint8_t i_sysPhase, - uint8_t i_override, - char *i_varName, - char *i_fnMetaData, - uint32_t verbose); +int p8_centaur_build( void *i_imageIn, + uint32_t i_ddLevel, + void *i_imageOut, + uint32_t i_sizeImageOutMax); + +int p8_ipl_build( void *i_imageIn, + uint32_t i_ddLevel, + void *i_imageOut, + uint32_t i_sizeImageOutMax); + +int get_ring_layout_from_image2( const void *i_imageIn, + uint32_t i_ddLevel, + uint8_t i_sysPhase, + DeltaRingLayout **o_rs4RingLayout, + void **nextRing); + +int write_ring_block_to_image( void *io_image, + DeltaRingLayout *i_ringBlock, + uint32_t i_sizeImageMax); + +int gen_ring_delta_state( + uint32_t bitLen, + uint32_t *i_init, + uint32_t *i_alter, + uint32_t *o_delta, + uint32_t verbose); + +int write_delta_ring_to_image( + char *i_fnImage, + CompressedScanData *i_RS4, + uint32_t i_ddLevel, + uint8_t i_sysPhase, + uint8_t i_override, + char *i_varName, + char *i_fnMetaData, + uint32_t verbose); int get_delta_ring_from_image( - char *i_fnImage, - char *i_varName, - uint32_t i_ddLevel, - uint8_t i_sysPhase, - uint8_t i_override, - MetaData **o_metaData, - CompressedScanData **o_deltaRingRS4, - uint32_t verbose); + char *i_fnImage, + char *i_varName, + uint32_t i_ddLevel, + uint8_t i_sysPhase, + uint8_t i_override, + MetaData **o_metaData, + CompressedScanData **o_deltaRingRS4, + uint32_t verbose); int write_wiggle_flip_to_image( - void *io_imageOut, - uint32_t *i_sizeImageMaxNew, - DeltaRingLayout *i_ringLayout, - uint32_t *i_wfInline, - uint32_t i_wfInlineLenInWords); - -int get_ring_layout_from_image( - const void *i_imageIn, - uint32_t i_ddLevel, - uint8_t i_sysPhase, - DeltaRingLayout *o_rs4RingLayout, - void **nextRing); - -int create_wiggle_flip_prg( + void *io_imageOut, + uint32_t *i_sizeImageMaxNew, + DeltaRingLayout *i_ringLayout, + uint32_t *i_wfInline, + uint32_t i_wfInlineLenInWords); + +int get_ring_layout_from_image( + const void *i_imageIn, + uint32_t i_ddLevel, + uint8_t i_sysPhase, + DeltaRingLayout *o_rs4RingLayout, + void **nextRing); + +int create_wiggle_flip_prg( uint32_t *i_deltaRing, uint32_t i_ringBitLen, uint32_t i_scanSelectData, - uint32_t i_chipletID, + uint32_t i_chipletID, uint32_t **o_wfInline, uint32_t *o_wfInlineLenInWords); int append_empty_section( - void *io_image, - uint32_t *i_sizeImageMaxNew, - uint32_t i_sectionId, - uint32_t i_sizeSection); + void *io_image, + uint32_t *i_sizeImageMaxNew, + uint32_t i_sectionId, + uint32_t i_sizeSection); + +int initialize_slw_section( + void *io_image, + uint32_t *i_sizeImageMaxNew); void cleanup( - void *buf1=NULL, - void *buf2=NULL, - void *buf3=NULL, - void *buf4=NULL, - void *buf5=NULL); - + void *buf1=NULL, + void *buf2=NULL, + void *buf3=NULL, + void *buf4=NULL, + void *buf5=NULL); + +#endif // End of not(SLW_COMMAND_LINE_RAM) + // Byte-reverse a 32-bit integer if on an LE machine inline uint32_t myRev32(const uint32_t i_x) { @@ -256,6 +306,12 @@ inline uint64_t myRev64(const uint64_t i_x) return rx; } +// N-byte align an address, offset or size (aos) +inline uint64_t myByteAlign( const uint8_t nBytes, const uint64_t aos) +{ + return (aos+nBytes-1)/nBytes*nBytes; +} + #ifdef __cplusplus } #endif diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_image_help.C b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_image_help.C index 6f0fe7af2..c2b17595e 100644 --- a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_image_help.C +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_image_help.C @@ -38,6 +38,8 @@ /*------------------------------------------------------------------------------*/ #include "p8_delta_scan_rw.h" +#include "p8_pore_table_gen_api.H" +#include "common_scom_addresses.H" #ifdef __FAPI #include <fapi.H> @@ -47,9 +49,9 @@ extern "C" { // get_ring_layout_from_image() // -int get_ring_layout_from_image( const void *i_imageIn, +int get_ring_layout_from_image( const void *i_imageIn, uint32_t i_ddLevel, - uint8_t i_sysPhase, + uint8_t i_sysPhase, DeltaRingLayout *o_rs4RingLayout, void **nextRing) { @@ -158,28 +160,31 @@ int get_ring_layout_from_image( const void *i_imageIn, sizeof(thisRingLayout->reserved2)); o_rs4RingLayout->rs4Launch = (uint32_t*)((uintptr_t)thisRingLayout + myRev64(thisRingLayout->entryOffset)); - // Since RS4 launch size is only word-aligned, make sure to point to nearest [higher] double-word boundary. - o_rs4RingLayout->rs4Delta = (uint32_t*)((((uintptr_t)thisRingLayout + + // entryOffset, rs4Launch and ASM_RS4_LAUNCH_BUF_SIZE should already be 8-byte aligned. + o_rs4RingLayout->rs4Delta = (uint32_t*)( (uintptr_t)thisRingLayout + myRev64(thisRingLayout->entryOffset) + - ASM_RS4_LAUNCH_BUF_SIZE-1)/8+1)*8); - - // Check that the ring layout structure in the memory is double-word aligned. This must be so because: - // - The entryOffset address must be on an 8-byte boundary because the start of the .initf ELF section must - // be 8-byte aligned AND because the rs4Delta member is the last member and which must itself be 8-byte aligned. - // - These two things together means that both the beginning and end of the delta ring layout must be 8-byte - // aligned, and thus the whole block,i.e. sizeOfThis, must be 8-byte aligned. - // Also check that the RS4 delta ring is double-word aligned. - // Also check that the RS4 launcher is word aligned. + ASM_RS4_LAUNCH_BUF_SIZE ); + + // Check that the ring layout structure in the memory is 8-byte aligned. This must + // be so because: + // - The entryOffset address must be on an 8-byte boundary because the start of the + // .rings section must be 8-byte aligned AND because the rs4Delta member is the + // last member and which must itself be 8-byte aligned. + // - These two things together means that both the beginning and end of the delta + // ring layout must be 8-byte aligned, and thus the whole block, i.e. sizeOfThis, + // must therefore automatically be 8-byte aligned. + // Also check that the RS4 delta ring is 8-byte aligned. + // Also check that the RS4 launcher is 8-byte aligned. // if (((uintptr_t)thisRingLayout-(uintptr_t)i_imageIn)%8 || myRev32(o_rs4RingLayout->sizeOfThis)%8 || - (uintptr_t)o_rs4RingLayout->rs4Launch%4 || - (uintptr_t)o_rs4RingLayout->rs4Delta%8) { - MY_ERR("ERROR : Ring layout is not double-word-aligned or RS4 launcher is not word aligned."); - MY_ERR(" thisRingLayout#8 = 0x%016llx",(uint64_t)thisRingLayout%8); - MY_ERR(" myRev32(o_rs4RingLayout->sizeOfThis)#8 = %i",myRev32(o_rs4RingLayout->sizeOfThis)%8); - MY_ERR(" o_rs4RingLayout->rs4Launch#4 = 0x%016llx",(uint64_t)o_rs4RingLayout->rs4Launch%4); - MY_ERR(" o_rs4RingLayout->rs4Delta#8 = 0x%016llx",(uint64_t)o_rs4RingLayout->rs4Delta%8); + myRev64(o_rs4RingLayout->entryOffset)%8 || + ASM_RS4_LAUNCH_BUF_SIZE%8) { + MY_ERR("ERROR : Ring block or layout structure is not 8-byte aligned:"); + MY_ERR(" thisRingLayout-imageIn = %i",(uintptr_t)thisRingLayout-(uintptr_t)i_imageIn); + MY_ERR(" o_rs4RingLayout->sizeOfThis = %i",myRev32(o_rs4RingLayout->sizeOfThis)); + MY_ERR(" o_rs4RingLayout->entryOffset = %i",(uint32_t)myRev64(o_rs4RingLayout->entryOffset)); + MY_ERR(" ASM_RS4_LAUNCH_BUF_SIZE = %i",(uint32_t)ASM_RS4_LAUNCH_BUF_SIZE); return IMGBUILD_ERR_MISALIGNED_RING_LAYOUT; } @@ -197,16 +202,17 @@ int get_ring_layout_from_image( const void *i_imageIn, // create_wiggle_flip_prg() function // Notes: -// - WF procedure needs to be updated with polling protocol. -// - WF procedure needs to reflect P0/P1 usage policy -int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta state +// - WF routine implements dynamic P1 multicast bit set based on P0 status. +// - WF routine checks header word on scan complete. +// - WF routine is 8-byte aligned. +int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta state (in BE format) uint32_t i_ringBitLen, // length of ring uint32_t i_scanSelectData, // Scan ring modifier data uint32_t i_chipletID, // Chiplet ID uint32_t **o_wfInline, // location of the PORE instructions data stream uint32_t *o_wfInlineLenInWords) // final length of data stream { - uint32_t rc=P8_PORE_SUCCESS_RC; //defined in p8_pore_api_const.h + uint32_t rc=0; //defined in p8_pore_api_const.h uint32_t i=0; uint32_t scanSelectAddr=0; uint32_t scanRing_baseAddr=0; @@ -214,16 +220,21 @@ int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta s uint32_t scanRingCheckWord=0; uint32_t count=0; uint32_t rotateLen=0, remainder=0, remainingBits=0; - uint32_t osIndex=0; int pgas_rc=0; uint64_t pore_imm64b=0; uint32_t maxWfInlineLenInWords = 10*MAX_RING_SIZE/32; PoreInlineContext ctx; - PoreInlineLocation src3=0, tgt3=0; *o_wfInline = (uint32_t*)malloc(maxWfInlineLenInWords); - //pore_inline_context_create(&ctx, buf, P8_PORE_BUFSIZE * 4, 0, PORE_INLINE_CHECK_PARITY); +/* Uncomment to dump ring state + printf("\n"); + for (i=0; i<i_ringBitLen/4; i++) { + printf("%02x",*((uint8_t*)i_deltaRing+i)); + if ((i+1)%32==0) printf("\n"); + } +*/ + pore_inline_context_create(&ctx, *o_wfInline, maxWfInlineLenInWords * 4, 0, 0); // Get chiplet and Ring Addr info. @@ -238,34 +249,35 @@ int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta s scanRing_poreAddr=scanRing_baseAddr; // Init scan ring rotate addr scanRingCheckWord=P8_SCAN_CHECK_WORD; // Header check word for checking ring write was successful - // Program scanselq reg for scan clock control setup before ring scan - // -------------------------------------------------------------------------- - #ifndef SLW_BUILD_WF_P0_FIX -// The following fix is a direct copy of the setp1_mcreadand macro in ./ipl/sbe/p8_slw.H + // This fix is a direct copy of the setp1_mcreadand macro in ./ipl/sbe/p8_slw.H uint64_t CLEAR_MC_TYPE_MASK=0x47; PoreInlineLocation src1=0, src2=0, tgt1=0, tgt2=0; - pgas_rc = pore_MR( &ctx, D1, P0) || - pore_ANDI( &ctx, D1, D1, BIT(57)) || - PORE_LOCATION( &ctx, src1) || - pore_BRANZ( &ctx, D1, src1) || - pore_MR( &ctx, P1, P0) || - PORE_LOCATION( &ctx, src2) || - pore_BRA( &ctx, tgt2) || - PORE_LOCATION( &ctx, tgt1) || - pore_MR( &ctx, D1, P0) || - pore_ANDI( &ctx, D1, D1, CLEAR_MC_TYPE_MASK) || - pore_ORI( &ctx, D1, D1, BIT(60)) || - pore_MR( &ctx, P1, D1) || - PORE_LOCATION( &ctx, tgt2); + pgas_rc = pore_MR( &ctx, D1, P0); + pgas_rc = pgas_rc + pore_ANDI( &ctx, D1, D1, BIT(57)); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, src1); + pgas_rc = pgas_rc + pore_BRANZ( &ctx, D1, src1); + pgas_rc = pgas_rc + pore_MR( &ctx, P1, P0); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, src2); + pgas_rc = pgas_rc + pore_BRA( &ctx, tgt2); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, tgt1); + pgas_rc = pgas_rc + pore_MR( &ctx, D1, P0); + pgas_rc = pgas_rc + pore_ANDI( &ctx, D1, D1, CLEAR_MC_TYPE_MASK); + pgas_rc = pgas_rc + pore_ORI( &ctx, D1, D1, BIT(60)); + pgas_rc = pgas_rc + pore_MR( &ctx, P1, D1); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, tgt2); if (pgas_rc>0) { MY_ERR("***setp1_mcreadand rc = %d", pgas_rc); return pgas_rc; } - pgas_rc = pore_inline_branch_fixup( &ctx, src1, tgt1) || - pore_inline_branch_fixup( &ctx, src2, tgt2); + pgas_rc = pore_inline_branch_fixup( &ctx, src1, tgt1); if (pgas_rc>0) { - MY_ERR("***inline_branch_fixup rc = %d", pgas_rc); + MY_ERR("***inline_branch_fixup error (1) rc = %d", pgas_rc); + return pgas_rc; + } + pgas_rc = pore_inline_branch_fixup( &ctx, src2, tgt2); + if (pgas_rc>0) { + MY_ERR("***inline_branch_fixup error (2) rc = %d", pgas_rc); return pgas_rc; } #else @@ -277,6 +289,7 @@ int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta s } #endif + // Program scanselq reg for scan clock control setup before ring scan pore_imm64b = ((uint64_t)i_scanSelectData) << 32; pgas_rc = pore_STI(&ctx, scanSelectAddr, P0, pore_imm64b); if (pgas_rc>0) { @@ -345,7 +358,7 @@ int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta s MY_DBG("base addr = 0x8%x, pore addr = 0x8%x, rotatelen = %d", scanRing_baseAddr, scanRing_poreAddr, rotateLen); //SCR1RD: shift out then read - pgas_rc=pore_LD(&ctx, D0, scanRing_poreAddr, P0); + pgas_rc=pore_LD(&ctx, D0, scanRing_poreAddr, P1); if (pgas_rc > 0) { MY_ERR("***LD D0 rc = %d", pgas_rc); return pgas_rc; @@ -359,9 +372,7 @@ int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta s else scanRing_poreAddr = scanRing_baseAddr | remainingBits; - //LI : Load XORed value to Scratch 1 reg. (same as p7+) - //TODO: Check why not overwrite with init values? - pore_imm64b = ((uint64_t)i_deltaRing[i]) << 32; + pore_imm64b = ((uint64_t)myRev32(i_deltaRing[i])) << 32; pgas_rc = pore_LI(&ctx, D0, pore_imm64b ); if (pgas_rc > 0) { @@ -396,7 +407,7 @@ int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta s // Rotate the chain and reset rotate length counter if (rotateLen>0xFC0) { scanRing_poreAddr = scanRing_baseAddr | rotateLen; - pgas_rc = pore_LD(&ctx, D0, scanRing_poreAddr, P0); + pgas_rc = pore_LD(&ctx, D0, scanRing_poreAddr, P1); if (pgas_rc > 0) { MY_ERR("***LD D0 rc = %d", pgas_rc); return pgas_rc; @@ -418,7 +429,7 @@ int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta s // shift the ring by remaining shift bit length if (rotateLen>0) { scanRing_poreAddr=scanRing_baseAddr | rotateLen; - pgas_rc = pore_LD(&ctx, D0, scanRing_poreAddr, P0); + pgas_rc = pore_LD(&ctx, D0, scanRing_poreAddr, P1); if (pgas_rc > 0) { MY_ERR("***LD D0 rc = %d", pgas_rc); return pgas_rc; @@ -427,32 +438,123 @@ int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta s } // Finally, check that our header check word went through in one piece. + // Note, we first do the MC-READ-AND check, then the MC-READ-OR check +#ifndef SLW_BUILD_WF_P0_FIX + // + // ...First, do the MC-READ-AND check + // (Reference: setp1_mcreadand macro in ./ipl/sbe/p8_slw.H) // + PoreInlineLocation src3=0, src5=0, src7=0, src8=0, tgt3=0, tgt5=0, tgt7=0, tgt8=0; + pgas_rc = pore_MR( &ctx, D1, P0); + pgas_rc = pgas_rc + pore_ANDI( &ctx, D1, D1, BIT(57)); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, src3); + pgas_rc = pgas_rc + pore_BRANZ( &ctx, D1, src3); + pgas_rc = pgas_rc + pore_MR( &ctx, P1, P0); // If here, MC=0. Omit MC check in OR case. + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, src7); + pgas_rc = pgas_rc + pore_BRA( &ctx, tgt7); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, tgt3); + pgas_rc = pgas_rc + pore_MR( &ctx, D1, P0); + pgas_rc = pgas_rc + pore_ANDI( &ctx, D1, D1, CLEAR_MC_TYPE_MASK); + pgas_rc = pgas_rc + pore_ORI( &ctx, D1, D1, BIT(60)); + pgas_rc = pgas_rc + pore_MR( &ctx, P1, D1); + if (pgas_rc>0) { + MY_ERR("***setp1_mcreadand rc = %d", pgas_rc); + return pgas_rc; + } + pgas_rc = pore_inline_branch_fixup( &ctx, src3, tgt3); + if (pgas_rc>0) { + MY_ERR("***inline_branch_fixup error (3) rc = %d", pgas_rc); + return pgas_rc; + } + // ...Load the output check word... + pgas_rc = pore_LD(&ctx, D0, scanRing_baseAddr, P1); + // Compare against the reference header check word... + pgas_rc = pgas_rc + pore_XORI( &ctx, D0, D0, ((uint64_t)scanRingCheckWord) << 32); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, src5); + pgas_rc = pgas_rc + pore_BRAZ( &ctx, D0, tgt5); + pgas_rc = pgas_rc + pore_HALT( &ctx); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, tgt5); + if (pgas_rc > 0) { + MY_ERR("***LD, XORI, BRANZ, RET or HALT went wrong rc = %d", pgas_rc); + return pgas_rc; + } + pgas_rc = pore_inline_branch_fixup( &ctx, src5, tgt5); + if (pgas_rc>0) { + MY_ERR("***inline_branch_fixup error (5) rc = %d", pgas_rc); + return pgas_rc; + } + // + // ...Now do the MC-READ-OR check + // (Reference: setp1_mcreador macro in ./ipl/sbe/p8_slw.H) + // Note. If we made is this far, we know that MC=1 already, so don't check for it. + // + pgas_rc = pore_MR( &ctx, D1, P0); + pgas_rc = pgas_rc + pore_ANDI( &ctx, D1, D1, CLEAR_MC_TYPE_MASK); // This also clears bit-60. + pgas_rc = pgas_rc + pore_MR( &ctx, P1, D1); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, tgt7); + if (pgas_rc>0) { + MY_ERR("***setp1_mcreadand rc = %d", pgas_rc); + return pgas_rc; + } + pgas_rc = pore_inline_branch_fixup( &ctx, src7, tgt7); + if (pgas_rc>0) { + MY_ERR("***inline_branch_fixup error (7) rc = %d", pgas_rc); + return pgas_rc; + } + // ...Load the output check word... + pgas_rc = pore_LD(&ctx, D0, scanRing_baseAddr, P1); + pgas_rc = pgas_rc + pore_XORI( &ctx, D0, D0, ((uint64_t)scanRingCheckWord) << 32); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, src8); + pgas_rc = pgas_rc + pore_BRAZ( &ctx, D0, tgt8); + pgas_rc = pgas_rc + pore_HALT( &ctx); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, tgt8); + pgas_rc = pgas_rc + pore_LI( &ctx, D0, 0x0); // Do shadowing by setpulse. + pgas_rc = pgas_rc + pore_STD( &ctx, D0, GENERIC_CLK_SCAN_UPDATEDR_0x0003A000, P0); + pgas_rc = pgas_rc + pore_RET( &ctx); + if (pgas_rc > 0) { + MY_ERR("***LD, XORI, BRANZ, RET or HALT went wrong rc = %d", pgas_rc); + return pgas_rc; + } + pgas_rc = pore_inline_branch_fixup( &ctx, src8, tgt8); + if (pgas_rc>0) { + MY_ERR("***inline_branch_fixup error (8) rc = %d", pgas_rc); + return pgas_rc; + } +#else + PoreInlineLocation src3=0, tgt3=0; // Load the output check word... - pgas_rc = pore_LD(&ctx, D0, scanRing_baseAddr, P0) | + pgas_rc = pore_LD(&ctx, D0, scanRing_baseAddr, P1); // Compare against the reference header check word... - pore_XORI( &ctx, D0, D0, ((uint64_t)scanRingCheckWord) << 32) | - // For now, branch to HALT instruction if not equal, otherwise return in the following instruction... - // But eventually branch to firmware error_handler if not equal - // pore_BRANZ(&ctx, D0, error_handler) || - PORE_LOCATION( &ctx, src3) | -// pore_BRANZ( &ctx, D0, ctx.lc+8) || // Jump two 4-byte instr (incl this one) to get to HALT. - pore_BRANZ( &ctx, D0, tgt3) | // Jump two 4-byte instr (incl this one) to get to HALT. - pore_RET( &ctx) | - PORE_LOCATION( &ctx, tgt3) | - pore_HALT( &ctx); + pgas_rc = pgas_rc + pore_XORI( &ctx, D0, D0, ((uint64_t)scanRingCheckWord) << 32); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, src3); + // For now, branch to HALT instruction if NZ, otherwise return in the following instr ..eventually branch to firmware error_handler i.e. pore_BRANZ(&ctx, D0, error_handler) + pgas_rc = pgas_rc + pore_BRANZ( &ctx, D0, tgt3); //pore_BRANZ( &ctx, D0, ctx.lc+8) + pgas_rc = pgas_rc + pore_RET( &ctx); + pgas_rc = pgas_rc + PORE_LOCATION( &ctx, tgt3); + pgas_rc = pgas_rc + pore_HALT( &ctx); if (pgas_rc > 0) { MY_ERR("***LD, XORI, BRANZ, RET or HALT went wrong rc = %d", pgas_rc); return pgas_rc; } pgas_rc = pore_inline_branch_fixup( &ctx, src3, tgt3); if (pgas_rc>0) { - MY_ERR("***inline_branch_fixup rc = %d", pgas_rc); + MY_ERR("***inline_branch_fixup error (3) rc = %d", pgas_rc); return pgas_rc; } +#endif - osIndex = ctx.lc/4; - *o_wfInlineLenInWords = osIndex; + *o_wfInlineLenInWords = ctx.lc/4; + + // 8-byte align code, just as a precaution. + if ((*o_wfInlineLenInWords*4)%8) { + // Insert 4-byte NOP at end. + pgas_rc = pore_NOP( &ctx); + if (pgas_rc>0) { + MY_ERR("***NOP went wrong rc = %d", pgas_rc); + return pgas_rc; + } + *o_wfInlineLenInWords = ctx.lc/4; + } return rc; } @@ -460,51 +562,47 @@ int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta s // write_wiggle_flip_to_image() -// 1 - mmap input image, -// 2 - Compose delta binary buffer containing RS4 launcher + RS4 delta data, -// 3 - Append delta buffer to .initf section. -// 4 - Save new image to output image file. -int write_wiggle_flip_to_image( void *io_imageOut, +int write_wiggle_flip_to_image( void *io_imageOut, uint32_t *i_sizeImageMaxNew, DeltaRingLayout *i_ringLayout, uint32_t *i_wfInline, uint32_t i_wfInlineLenInWords) { uint32_t rc=0, bufLC; + int deltaLC, i; uint32_t sizeImageIn, sizeNewDataBlock; uint32_t sizeImageOutThisEst=0, sizeImageOutThis=0; - void *initfBuffer=NULL; + void *ringsBuffer=NULL; uint32_t ringRingsOffset=0; uint64_t ringPoreAddress=0,backPtr=0,fwdPtr=0,fwdPtrCheck; - SBE_XIP_ERROR_STRINGS(errorStrings); + SBE_XIP_ERROR_STRINGS(errorStrings); MY_DBG("wfInlineLenInWords=%i", i_wfInlineLenInWords); // Modify the input ring layout content - // - Remove the qualifier section: ddLevel, sysPhase, override and reserved1+2. This means - // reducing the entryOffset by the size of these qualifiers. - // - Adjust sizeOfThis - // - Use new wfInline member of ring layout struct. - // - Ignore the rs4Delta member - // - // For sizeOfThis, we must ensure 4-byte alignment WF code. That is easy since both entryOffset - // and wfInlineLenInWord are already word-aligned. + // - Remove the qualifier section: ddLevel, sysPhase, override and reserved1+2. + // This means reducing the entryOffset by the size of these qualifiers. + // - The new WF ring block and start of WF code must both be 8-byte aligned. + // - RS4 entryOffset is already 8-byte aligned. + // - The WF code section, i.e. wfInlineLenInWords, is already 8-byte aligned. // - i_ringLayout->entryOffset = myRev64( myRev64(i_ringLayout->entryOffset) - - sizeof(i_ringLayout->ddLevel) - - sizeof(i_ringLayout->sysPhase) - - sizeof(i_ringLayout->override) - - sizeof(i_ringLayout->reserved1) - - sizeof(i_ringLayout->reserved2) ); - i_ringLayout->sizeOfThis = myRev32( myRev64(i_ringLayout->entryOffset) + - i_wfInlineLenInWords*4 ); + i_ringLayout->entryOffset = + myRev64( myByteAlign(8, myRev64(i_ringLayout->entryOffset) - + sizeof(i_ringLayout->ddLevel) - + sizeof(i_ringLayout->sysPhase) - + sizeof(i_ringLayout->override) - + sizeof(i_ringLayout->reserved1) - + sizeof(i_ringLayout->reserved2) ) ); + i_ringLayout->sizeOfThis = + myRev32( myRev64(i_ringLayout->entryOffset) + i_wfInlineLenInWords*4 ); + // Not really any need for this. Just being consistent. Once we have transitioned completely to new // headers, then ditch i_wfInline from parm list and assign wfInline to layout in main program. i_ringLayout->wfInline = i_wfInline; - if (((uintptr_t)i_ringLayout)%4 || myRev64(i_ringLayout->entryOffset)%4) { - MY_ERR("ERROR : Ring layout is not word-aligned."); + if (myRev64(i_ringLayout->entryOffset)%8 || myRev32(i_ringLayout->sizeOfThis)%8) { + MY_ERR("ERROR : Ring block or WF code origin not 8-byte aligned."); return IMGBUILD_ERR_MISALIGNED_RING_LAYOUT; } @@ -517,63 +615,82 @@ int write_wiggle_flip_to_image( void *io_imageOut, } sizeNewDataBlock = myRev32(i_ringLayout->sizeOfThis); // ...estimate max size of new image - sizeImageOutThisEst = sizeImageIn + sizeNewDataBlock + SBE_XIP_MAX_SECTION_ALIGNMENT; // + sizeImageOutThisEst = sizeImageIn + sizeNewDataBlock + SBE_XIP_MAX_SECTION_ALIGNMENT; // if (sizeImageOutThisEst>*i_sizeImageMaxNew) { MY_ERR("ERROR : Estimated new image size (=%i) would exceed max allowed size (=%i).", sizeImageOutThisEst, *i_sizeImageMaxNew); - *i_sizeImageMaxNew = sizeImageOutThisEst; + *i_sizeImageMaxNew = sizeImageOutThisEst; return IMGBUILD_ERR_IMAGE_TOO_LARGE; } - MY_DBG("Input image size\t\t= %6i\n\tNew initf data block size\t= %6i\n\tOutput image size\t\t<=%6i", + MY_DBG("Input image size\t\t= %6i\n\tNew rings data block size\t= %6i\n\tOutput image size (max)\t\t<=%6i", sizeImageIn, sizeNewDataBlock, sizeImageOutThisEst); MY_DBG("entryOffset = %i\n\tsizeOfThis = %i\n\tMeta data size = %i", (uint32_t)myRev64(i_ringLayout->entryOffset), myRev32(i_ringLayout->sizeOfThis), myRev32(i_ringLayout->sizeOfMeta)); MY_DBG("Back item ptr = 0x%016llx",myRev64(i_ringLayout->backItemPtr)); - MY_DBG("DD level = %i\n\tSys phase = %i\n\tOverride = %i\n\tReserved1+2 = %i", + MY_DBG("DD level = 0x%02x\n\tSys phase = %i\n\tOverride = %i\n\tReserved1+2 = %i", myRev32(i_ringLayout->ddLevel), i_ringLayout->sysPhase, i_ringLayout->override, i_ringLayout->reserved1|i_ringLayout->reserved2); - // Combine rs4RingLayout members into a unified buffer (initfBuffer). + // Combine rs4RingLayout members into a unified buffer (ringsBuffer). // - initfBuffer = malloc((size_t)sizeNewDataBlock); - if (initfBuffer == NULL) { + ringsBuffer = malloc((size_t)sizeNewDataBlock); + if (ringsBuffer == NULL) { MY_ERR("ERROR : malloc() of initf buffer failed."); return IMGBUILD_ERR_MEMORY; } - // ... and copy the WF ring layout content into initfBuffer in BIG-ENDIAN format. + // ... First, copy WF ring layout header into ringsBuffer in BIG-ENDIAN format. bufLC = 0; - memcpy( (uint8_t*)initfBuffer+bufLC, &i_ringLayout->entryOffset, (uintptr_t)&i_ringLayout->metaData-(uintptr_t)&i_ringLayout->entryOffset); - bufLC = (uintptr_t)&i_ringLayout->metaData-(uintptr_t)&i_ringLayout->entryOffset; - memcpy( (uint8_t*)initfBuffer+bufLC, i_ringLayout->metaData, myRev32(i_ringLayout->sizeOfMeta)); - - bufLC = (uint32_t)myRev64(i_ringLayout->entryOffset); - // The above forces word-alignment of bufLC as [previous] metaData member is only byte aligned. - memcpy( (uint8_t*)initfBuffer+bufLC, i_wfInline, i_wfInlineLenInWords*4); + deltaLC = (uintptr_t)&i_ringLayout->ddLevel-(uintptr_t)&i_ringLayout->entryOffset; + memcpy( (uint8_t*)ringsBuffer+bufLC, &i_ringLayout->entryOffset, deltaLC); + // ... then meta data + bufLC = bufLC + deltaLC; + deltaLC = myRev32(i_ringLayout->sizeOfMeta); + memcpy( (uint8_t*)ringsBuffer+bufLC, i_ringLayout->metaData, deltaLC); + // ... Is this padding or WF buffer? + bufLC = bufLC + deltaLC; + deltaLC = (uint32_t)myRev64(i_ringLayout->entryOffset) - bufLC; + if (deltaLC<0 || deltaLC>=8) { + MY_ERR("ERROR : Ring layout mess. Check code or delta_scan(). deltaLC=%i",deltaLC); + return IMGBUILD_ERR_CHECK_CODE; + } + if (deltaLC>0) { + // OK, it's padding time. + for (i=0; i<deltaLC; i++) + *(uint8_t*)((uint8_t*)ringsBuffer+bufLC+i) = 0; + } + // ... now do the WF buffer + bufLC = bufLC + deltaLC; + if (bufLC!=(uint32_t)myRev64(i_ringLayout->entryOffset)) { + MY_ERR("ERROR : Ring layout messup. Check code or delta_scan()."); + return IMGBUILD_ERR_CHECK_CODE; + } + deltaLC = i_wfInlineLenInWords*4; + memcpy( (uint8_t*)ringsBuffer+bufLC, i_wfInline, deltaLC); // Append WF ring layout to .rings section of in-memory input image. - // Note! All layout members should already be 4-byte-aligned. + // Note! All layout members should already be 8-byte aligned. // rc = sbe_xip_append( io_imageOut, SBE_XIP_SECTION_RINGS, - (void*)initfBuffer, + (void*)ringsBuffer, sizeNewDataBlock, sizeImageOutThisEst, &ringRingsOffset); MY_DBG("ringRingsOffset=0x%08x",ringRingsOffset); if (rc) { MY_ERR("ERROR : sbe_xip_append() failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc)); - if (initfBuffer) free(initfBuffer); + if (ringsBuffer) free(ringsBuffer); return IMGBUILD_ERR_XIP_MISC; } // ...get new image size, update return size, and test if successful update. sbe_xip_image_size( io_imageOut, &sizeImageOutThis); MY_DBG("Output image size (final)\t=%i",sizeImageOutThis); - *i_sizeImageMaxNew = sizeImageOutThis; + *i_sizeImageMaxNew = sizeImageOutThis; rc = sbe_xip_validate( io_imageOut, sizeImageOutThis); if (rc) { MY_ERR("ERROR : sbe_xip_validate() of output image failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc)); - if (initfBuffer) free(initfBuffer); + if (ringsBuffer) free(ringsBuffer); return IMGBUILD_ERR_XIP_MISC; } MY_DBG("Successful append of RS4 ring to .rings. Next, update forward ptr..."); @@ -586,7 +703,7 @@ int write_wiggle_flip_to_image( void *io_imageOut, MY_DBG("fwdPtr=0x%016llx", fwdPtr); if (rc) { MY_ERR("ERROR : sbe_xip_section2pore() failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc)); - if (initfBuffer) free(initfBuffer); + if (ringsBuffer) free(ringsBuffer); return IMGBUILD_ERR_XIP_MISC; } // ...then update the forward pointer, i.e. the old "variable/ring name's" pointer. @@ -603,7 +720,7 @@ int write_wiggle_flip_to_image( void *io_imageOut, &fwdPtrCheck); if (rc) { MY_ERR("ERROR : sbe_xip_[write,read]_uint64() failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc)); - if (initfBuffer) free(initfBuffer); + if (ringsBuffer) free(ringsBuffer); return IMGBUILD_ERR_XIP_MISC; } if (fwdPtrCheck!=ringPoreAddress || backPtr!=myRev64(i_ringLayout->backItemPtr)) { @@ -612,7 +729,7 @@ int write_wiggle_flip_to_image( void *io_imageOut, MY_ERR("fwdPtrCheck =0x%016llx",fwdPtrCheck); MY_ERR("layout bckPtr=0x%016llx",myRev64(i_ringLayout->backItemPtr)); MY_ERR("backPtr =0x%016llx",backPtr); - if (initfBuffer) free(initfBuffer); + if (ringsBuffer) free(ringsBuffer); return IMGBUILD_ERR_FWD_BACK_PTR_MESS; } // ...test if successful update. @@ -622,11 +739,11 @@ int write_wiggle_flip_to_image( void *io_imageOut, MY_ERR("Probable cause:"); MY_ERR("\tsbe_xip_write_uint64() updated at the wrong address (=0x%016llx)", myRev64(i_ringLayout->backItemPtr)); - if (initfBuffer) free(initfBuffer); + if (ringsBuffer) free(ringsBuffer); return IMGBUILD_ERR_XIP_MISC; } - if (initfBuffer) free(initfBuffer); + if (ringsBuffer) free(ringsBuffer); return rc; } @@ -657,11 +774,11 @@ int append_empty_section( void *io_image, // sbe_xip_image_size( io_image, &sizeImageIn); // ...estimate max size of new image - sizeImageOutThisEst = sizeImageIn + i_sizeSection + SBE_XIP_MAX_SECTION_ALIGNMENT; + sizeImageOutThisEst = sizeImageIn + i_sizeSection + SBE_XIP_MAX_SECTION_ALIGNMENT; if (sizeImageOutThisEst>*i_sizeImageMaxNew) { MY_ERR("ERROR : Estimated new image size (=%i) would exceed max allowed size (=%i).", sizeImageOutThisEst, *i_sizeImageMaxNew); - *i_sizeImageMaxNew = sizeImageOutThisEst; + *i_sizeImageMaxNew = sizeImageOutThisEst; return IMGBUILD_ERR_IMAGE_TOO_LARGE; } @@ -685,7 +802,7 @@ int append_empty_section( void *io_image, // ...get new image size, update return size, and test if successful update. sbe_xip_image_size( io_image, &sizeImageOutThis); MY_DBG("Output image size (final)\t=%i",sizeImageOutThis); - *i_sizeImageMaxNew = sizeImageOutThis; + *i_sizeImageMaxNew = sizeImageOutThis; rc = sbe_xip_validate( io_image, sizeImageOutThis); if (rc) { MY_ERR("ERROR : xip_validate() of output image failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc)); @@ -701,6 +818,101 @@ int append_empty_section( void *io_image, +// initialize_slw_section() +// - allocate space for Ramming and Scomming +// - populate Scomming table with ret/nop/nop/nop (RNNN) inline asm instructions +// - update Scomming vector +int initialize_slw_section( void *io_image, + uint32_t *i_sizeImageMaxNew) +{ + uint32_t rc=0, i_coreId=0, i_iis=0; + int pgas_rc=0; + void *bufRNNN=NULL; + PoreInlineContext ctx; + SbeXipSection xipSection; + SbeXipItem xipTocItem; + void *hostScomTableFirst, *hostScomTableNext, *hostScomVectorFirst, *hostScomVectorNext; + uint64_t xipScomTableFirst; + + SBE_XIP_ERROR_STRINGS(errorStrings); + + rc = 0; + + rc = append_empty_section( io_image, + i_sizeImageMaxNew, + SBE_XIP_SECTION_SLW, + SLW_RAM_TABLE_SIZE + SLW_SCOM_TABLE_SIZE); + if (rc) + return rc; + + // + // Ramming table: Nothing to do. Already 0-initialized in append_empty_section(). + // + + // + // Scomming table: Fill with RNNN (16-byte) instruction sequences. + // + + // ... allocate buffer to hold one RNNN instruction sequence. + bufRNNN = malloc( XIPSIZE_SCOM_ENTRY); + + // ... create RNNN instruction sequence. + pore_inline_context_create( &ctx, bufRNNN, XIPSIZE_SCOM_ENTRY, 0, 0); + pgas_rc = pore_RET( &ctx); + pgas_rc = pgas_rc + pore_NOP( &ctx); + pgas_rc = pgas_rc + pore_NOP( &ctx); + pgas_rc = pgas_rc + pore_NOP( &ctx); + if (pgas_rc>0) { + MY_ERR("***_RET or _NOP generated rc = %d", pgas_rc); + if (bufRNNN) free(bufRNNN); + return IMGBUILD_ERR_PORE_INLINE_ASM; + } + + // ... get host and pore location of Scom table in .slw section. + rc = sbe_xip_get_section( io_image, SBE_XIP_SECTION_SLW, &xipSection); + if (rc) { + MY_ERR("ERROR : sbe_xip_get_section() failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc)); + MY_ERR("Probable cause:"); + MY_ERR("\tThe section (=SBE_XIP_SECTION_SLW=%i) was not found.",SBE_XIP_SECTION_SLW); + if (bufRNNN) free(bufRNNN); + return IMGBUILD_ERR_KEYWORD_NOT_FOUND; + } + hostScomTableFirst = (void*)((uintptr_t)io_image + xipSection.iv_offset + SLW_RAM_TABLE_SIZE); + sbe_xip_host2pore( io_image, hostScomTableFirst, &xipScomTableFirst); + +//#ifdef DUMMY_DEF1 // Undo this ifdef once Scom vector name is defined in TOC. + // ... get location of Scom vector from TOC. + rc = sbe_xip_find( io_image, SLW_HOST_SCOM_VECTOR_TOC_NAME, &xipTocItem); + if (rc) { + MY_ERR("ERROR : sbe_xip_find() failed w/rc=%i and %s", rc, SBE_XIP_ERROR_STRING(errorStrings, rc)); + MY_ERR("Probable cause:"); + MY_ERR("\tThe keyword (=%s) was not found.",SLW_HOST_SCOM_VECTOR_TOC_NAME); + if (bufRNNN) free(bufRNNN); + return IMGBUILD_ERR_KEYWORD_NOT_FOUND; + } + rc = sbe_xip_pore2host( io_image, xipTocItem.iv_address, &hostScomVectorFirst); + + // ... populate entire Scom table with RNNN IIS. + for (i_iis=0; i_iis<SLW_SCOM_TABLE_SIZE; i_iis=i_iis+XIPSIZE_SCOM_ENTRY) { + hostScomTableNext = (void*)( (uintptr_t)hostScomTableFirst + i_iis); + memcpy( hostScomTableNext, bufRNNN, XIPSIZE_SCOM_ENTRY); + } + + // ... update Scom vector. + for (i_coreId=0; i_coreId<SLW_MAX_CORES; i_coreId++) { + hostScomVectorNext = (void*)( (uint64_t*)hostScomVectorFirst + i_coreId); + *(uint64_t*)hostScomVectorNext = myRev64( xipScomTableFirst + + SLW_SCOM_TABLE_SPACE_PER_CORE*i_coreId); + } +//#endif + + if (bufRNNN) free(bufRNNN); + + return rc; +} + + + void cleanup( void *buf1, void *buf2, void *buf3, diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_const.h b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_const.h index 43a2a3e5c..1f0f86ada 100644 --- a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_const.h +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_const.h @@ -21,23 +21,23 @@ * * IBM_PROLOG_END_TAG */ -/* $Id: p8_pore_api_const.h,v 1.1 2011/08/25 12:32:33 yjkim Exp $ */ +/* $Id: p8_pore_api_const.h,v 1.2 2012/06/11 20:55:00 cmolsen Exp $ */ /* $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/utils/p8_pore_api_const.h,v $ */ /** * Contains any constants uses as inputs or outputs to the p7p_pore functions */ - +// CMO-20120601: SCOM Operators moved to p8_pore_table_gen_api.H /****************************/ /***** SCOM Operators *****/ /****************************/ -#define P8_PORE_SCOM_APPEND 0 /* add scom instructions to the end of the existing image */ -#define P8_PORE_SCOM_REPLACE 1 /* replace existing instructions with new data */ -#define P8_PORE_SCOM_OR 2 /* overlay scom data onto existing instruction by bitwise OR */ -#define P8_PORE_SCOM_AND 3 /* overlay scom data onto existing instruction by bitwise AND */ -#define P8_PORE_SCOM_NOOP 4 /* replace existing instructions with NOP */ -#define P8_PORE_SCOM_LAST_OP 4 /* keep track of the last op for checking correctness of op input */ +//#define P8_PORE_SCOM_APPEND 0 /* add scom instructions to the end of the existing image */ +//#define P8_PORE_SCOM_REPLACE 1 /* replace existing instructions with new data */ +//#define P8_PORE_SCOM_OR 2 /* overlay scom data onto existing instruction by bitwise OR */ +//#define P8_PORE_SCOM_AND 3 /* overlay scom data onto existing instruction by bitwise AND */ +//#define P8_PORE_SCOM_NOOP 4 /* replace existing instructions with NOP */ +//#define P8_PORE_SCOM_LAST_OP 4 /* keep track of the last op for checking correctness of op input */ /***************************/ @@ -82,6 +82,10 @@ This section is automatically updated by CVS when you check in this file. Be sure to create CVS comments when you commit so that they can be included here. $Log: p8_pore_api_const.h,v $ +Revision 1.2 2012/06/11 20:55:00 cmolsen +Updated to comment out the Scom operation defines which are now defined in +p8_pore_table_gen_api.H instead. + Revision 1.1 2011/08/25 12:32:33 yjkim initial checkin diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_table_gen_api.H b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_table_gen_api.H deleted file mode 100644 index a99cbc99e..000000000 --- a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_table_gen_api.H +++ /dev/null @@ -1,168 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG - * This is an automatically generated prolog. - * - * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_table_gen_api.H $ - * - * IBM CONFIDENTIAL - * - * COPYRIGHT International Business Machines Corp. 2012 - * - * p1 - * - * Object Code Only (OCO) source materials - * Licensed Internal Code Source Materials - * IBM HostBoot Licensed Internal Code - * - * The source code for this program is not published or other- - * wise divested of its trade secrets, irrespective of what has - * been deposited with the U.S. Copyright Office. - * - * Origin: 30 - * - * IBM_PROLOG_END_TAG - */ -/*------------------------------------------------------------------------------*/ -/* *! (C) Copyright International Business Machines Corp. 2012 */ -/* *! All Rights Reserved -- Property of IBM */ -/* *! *** IBM Confidential *** */ -/*------------------------------------------------------------------------------*/ -/* *! TITLE : p8_pore_table_gen_api */ -/* *! DESCRIPTION : Contains all external APIs used by firmware (PHYP) to */ -// generate/modify the P8 PORE SLW image. -/* *! OWNER NAME : Michael Olsen Email: cmolsen@us.ibm.com */ -/* *! ADDITIONAL COMMENTS : */ -// - Start file: p7p_pore_api.h -// - _table_entry structs must agree with Greg's proc_slw_ram.H -// -/*------------------------------------------------------------------------------*/ - -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> - -#include "pore_bitmanip.H" -#include "sbe_xip_image.h" - -//#ifndef _P8_PORE_API_H -//#define _P8_PORE_API_H - -//#include <p8_pore_api_custom.h> -//#include <p8_pore_image.h> -//#include <p8_pore_api_const.h> - -/* Common header for *.c and .S ramming code: Call it ../sbe/proc_slw_ram.H ? */ -// Header defs (P8&PORE 64-bit notation where bits are numbered from left-to-right) -#define RAM_HEADER_END_START 0 -#define RAM_HEADER_END_MASK BITS(RAM_HEADER_END_START,1) -#define RAM_HEADER_TYPE_START 2 -#define RAM_HEADER_TYPE_MASK BITS(RAM_HEADER_TYPE_START,2) -#define RAM_HEADER_SPRN_START 4 -#define RAM_HEADER_SPRN_MASK BITS(RAM_HEADER_SPRN_START,10) -#define RAM_HEADER_THREAD_START 16 -#define RAM_HEADER_THREAD_MASK BITS(RAM_HEADER_THREAD_START,3) -// MTSPR instr defs -#define RAM_MTSPR_INSTR_TEMPL ( ( (uint64_t)31<<(63-5) | (uint64_t)467<<(63-30) ) ) -#define RAM_MTSPR_SPR_START 11 -#define RAM_MTSPR_SPR_MASK BITS(RAM_MTSPR_SPR_START,10) -// Header defs (C notation where bits are numbered from right-to-left, and reducing to 32-bit) -#define RAM_HEADER_END_START_C ( 31-RAM_HEADER_END_START+1-1 ) -#define RAM_HEADER_END_MASK_C (uint32_t)(RAM_HEADER_END_MASK>>32) -#define RAM_HEADER_TYPE_START_C ( 31-RAM_HEADER_TYPE_START+1-2 ) -#define RAM_HEADER_TYPE_MASK_C (uint32_t)(RAM_HEADER_TYPE_MASK>>32) -#define RAM_HEADER_SPRN_START_C ( 31-RAM_HEADER_SPRN_START+1-10 ) -#define RAM_HEADER_SPRN_MASK_C (uint32_t)(RAM_HEADER_SPRN_MASK>>32) -#define RAM_HEADER_THREAD_START_C ( 31-RAM_HEADER_THREAD_START+1-3 ) -#define RAM_HEADER_THREAD_MASK_C (uint32_t)(RAM_HEADER_THREAD_MASK>>32) -// MTSPR instr defs -#define RAM_MTSPR_INSTR_TEMPL_C ( ( (uint32_t)31<<(31-5) | (uint32_t)467<<(31-30) ) ) -#define RAM_MTSPR_SPR_START_C ( 31-RAM_MTSPR_SPR_START+1-10 ) -//#define RAM_MTSPR_SPR_MASK_C (uint32_t)(BITS(RAM_MTSPR_SPR_START,10)>>32) -#define RAM_MTSPR_SPR_MASK_C (uint32_t)(RAM_MTSPR_SPR_MASK>>32) - -/* Other defs needed for ramming */ -// TOC names -#define SLW_HOST_REG_VECTOR_TOC_NAME "slw_host_reg_vector" -#define SLW_HOST_SCOM_VECTOR_TOC_NAME "slw_host_scom_vector" -#define SLW_HOST_REG_TABLE_TOC_NAME "slw_core_reg_table" - -// Defines for slw_build() to update "host_runtime_scome" w/pointer to "slw_host_runtime" at SLW image build time. -#define HOST_RUNTIME_SCOM_TOC_NAME "host_runtime_scom" // Null 1st, then fill w/addr of SLW_HOST_RUNTIME_TOC_NAME -#define SLW_HOST_RUNTIME_TOC_NAME "slw_host_runtime" - - -// RAM table defines -#define XIPSIZE_RAM_ENTRY ( (sizeof(RamTableEntry)+7)/8*8 ) -#define SLW_MAX_CORES 16 -#define SLW_MAX_CPUREGS_CORE 8 -#define SLW_MAX_CPUREGS_THREADS 3 -#define SLW_CORE_THREADS 8 -#define SLW_MAX_CPUREGS_OPS ( SLW_MAX_CPUREGS_CORE + \ - SLW_CORE_THREADS*SLW_MAX_CPUREGS_THREADS ) -#define SLW_SLW_SECTION_SIZE ( SLW_MAX_CORES * SLW_MAX_CPUREGS_OPS * XIPSIZE_RAM_ENTRY ) - -// Return codes -#define SLW_RAM_SUCCESS 0 -#define SLW_RAM_HEADERS_NOT_SYNCED 1 -#define SLW_RAM_IMAGE_SIZE_MISMATCH 2 -#define SLW_RAM_TABLE_ENTRY_OVERFLOW 3 -#define SLW_RAM_CODE_ERROR 4 -#define SLW_RAM_INVALID_PARAMETER 5 -#define SLW_RAM_WARNING_TABLE_CONTAMINATION 10 - -#ifdef __cpluscplus -extern "C" { -#endif - -typedef struct ram_instr_t { - uint32_t header; - uint32_t instr; - uint64_t data; -} RamTableEntry; - -// SLW supported SPR registers -typedef struct { - const char *name; - uint32_t value; - uint32_t swizzled; -} SlwSprRegs; - -const SlwSprRegs SLW_SPR_REGS[] = { - /* name value swizzled */ - // ...core regs - { "P8_SPR_HRMOR", 313, ( 313>>5 | ( 313&0x1f)<<5 ) }, - { "P8_SPR_HMEER", 337, ( 337>>5 | ( 337&0x1f)<<5 ) }, - { "P8_SPR_PMICR", 852, ( 852>>5 | ( 852&0x1f)<<5 ) }, - { "P8_SPR_PMCR", 884, ( 884>>5 | ( 884&0x1f)<<5 ) }, - { "P8_SPR_HID0", 1008, ( 1008>>5 | (1008&0x1f)<<5 ) }, - { "P8_SPR_HID1", 1009, ( 1009>>5 | (1009&0x1f)<<5 ) }, - { "P8_SPR_HID4", 1012, ( 1012>>5 | (1012&0x1f)<<5 ) }, - { "P8_SPR_HID5", 1014, ( 1014>>5 | (1014&0x1f)<<5 ) }, - // ...thread regs - { "P8_SPR_HSPRG0", 304, ( 304>>5 | ( 304&0x1f)<<5 ) }, - { "P8_SPR_LPCR", 318, ( 318>>5 | ( 318&0x1f)<<5 ) }, - // Greg, this is NOT in jbishop's SS. Got it from ur ST. But 1023 is max! - { "P8_SPR_MSR", 2000, ( 2000>>5 | (2000&0x1f)<<5 ) } -}; - -const int SLW_SPR_REGS_SIZE = sizeof(SLW_SPR_REGS)/sizeof(SLW_SPR_REGS[0]); - - -/* Name: p8_pore_gen_cpureg() - * Description: Populates ramming entries in the .slw section - * Parameter list: i_image - pointer to SLW mainstore image - * i_sizeImage - size of SLW mainstore image - * i_regName - unswizzled SPR register value - * i_regData - data to write to SPR register - * i_coreId - the core ID to operate on - * i_threadId - the thread ID to operate on - */ -uint32_t p8_pore_gen_cpureg(void *i_image, - uint32_t i_sizeImage, - uint32_t i_regName, - uint64_t i_regData, - uint32_t i_coreId, - uint32_t i_threadId); - -#ifdef __cpluscplus -} -#endif diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.C b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.C index 3744f1fea..af54eb656 100644 --- a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.C +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.C @@ -25,32 +25,38 @@ /* *! TITLE : proc_slw_build */ /* *! DESCRIPTION : Extracts and decompresses delta ring states from EPROM */ // image. Utilizes the linked list approach (LLA) to extract -// and position wiggle-flip programs in .rings according to -// back pointer, DD level, phase and override settings. +// and position wiggle-flip programs in .rings according to +// back pointer, DD level, phase and override settings. /* *! OWNER NAME : Michael Olsen cmolsen@us.ibm.com */ // /* *! EXTENDED DESCRIPTION : */ // /* *! USAGE : To build (for Hostboot) - */ // buildfapiprcd -r ver-12-5 -C "p8_image_help.C,p8_scan_compression.C" -c "sbe_xip_image.c,pore_inline_assembler.c,pore_inline_disassembler.c,p8_pore_static_data.c" -e "../../xml/error_info/proc_slw_build_errors.xml" proc_slw_build.C -// Parameter list - +// Parameter list - // See function definition below. -// Alternative usages - -// To build for scanning by EPM team: -// buildfapiprcd_cmo -u "SLW_BUILD_WF_P0_FIX,SLW_BUILD_SYSPHASE_ZERO_MODE,SLW_COMMAND_LINE" -r ... +// Alternative usages - +// To build for scanning by EPM team w/fixed P0 value, sysPhase=0, +// always-return-after-wf, command-line mode: +// buildfapiprcd -u "SLW_BUILD_WF_P0_FIX,SLW_BUILD_SYSPHASE_ZERO_MODE,SLW_BUILD_WF_RETURN,SLW_COMMAND_LINE" -r ... // /* *! ASSUMPTIONS : */ -// - For proc_slw_build, sysPhase=1 is assumed during real hostboot. +// - For Hostboot environment: +// - dynamic P0/P1 calculation +// - sysPhase=1 +// - check header word after WF +// - non-command-line mode, FAPI call // /* *! COMMENTS : */ // - All image content, incl .initf content and ring layout, is handled // in BE format. No matter which platform. -// - A ring may only be requested with the sysPhase=0 or 1. Any other +// - A ring may only be requested with the sysPhase=0 or 1. Any other // sysPhase value, incl sysPhase=2, will cause no rings to be found. // /*------------------------------------------------------------------------------*/ #include "proc_slw_build.H" +#include "p8_delta_scan_rw.h" extern "C" { @@ -77,7 +83,7 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, #else uint8_t sysPhase=1; #endif - + uint32_t rcLoc=0, rcSearch=0, i, countWF=0; uint32_t sizeImage=0, sizeImageOutMax, sizeImageTmp, sizeImageOld; uint8_t *deltaRingDxed=NULL; @@ -85,13 +91,13 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, DeltaRingLayout rs4RingLayout; void *nextRing=NULL; - uint32_t ringBitLen=0, ringByteLen=0, ringTrailBits=0; + uint32_t ringBitLen=0; //ringByteLen=0, ringTrailBits=0; uint32_t *wfInline=NULL; uint32_t wfInlineLenInWords; sizeImageOutMax = *io_sizeImageOut; - + if (sizeImageOutMax<i_sizeImageIn) { FAPI_ERR("Inp image size (from caller): %i",i_sizeImageIn); FAPI_ERR("Max image size (from caller): %i",*io_sizeImageOut); @@ -100,7 +106,7 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_INPUT_IMAGE_SIZE_MESS); return rc; } - + // ========================================================================== // Check and copy image to mainstore and clean it up. @@ -128,7 +134,7 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, return rc; } FAPI_DBG("Image size (in EPROM): %i",i_sizeImageIn); - + // Second, copy input image to supplied mainstore location. // memcpy( i_imageOut, i_imageIn, i_sizeImageIn); @@ -188,11 +194,11 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, // ========================================================================== // Get DD level from FAPI attributes. // ========================================================================== - // $$rc = FAPI_ATTR_GET(ATTR_EC, &i_target, l_uint8); +// rc = FAPI_ATTR_GET(ATTR_EC, &i_target, l_uint8); rc = FAPI_ATTR_GET_PRIVILEGED(ATTR_EC, &i_target, l_uint8); ddLevel = (uint32_t)l_uint8; if (rc) { - FAPI_ERR("FAPI_ATTR_GET() failed w/rc=%i and ddLevel=0x%02x",(uint32_t)rc,l_uint8); + FAPI_ERR("FAPI_ATTR_GET_PRIVILEGED() failed w/rc=%i and ddLevel=0x%02x",(uint32_t)rc,l_uint8); return rc; } @@ -202,7 +208,7 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, do { FAPI_DBG("nextRing (at top)=0x%016llx",(uint64_t)nextRing); - + // ========================================================================== // Get ring layout from image @@ -214,8 +220,8 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, &rs4RingLayout, &nextRing); rcSearch = rcLoc; - if (rcSearch!=DSLWB_RING_SEARCH_MATCH && - rcSearch!=DSLWB_RING_SEARCH_EXHAUST_MATCH && + if (rcSearch!=DSLWB_RING_SEARCH_MATCH && + rcSearch!=DSLWB_RING_SEARCH_EXHAUST_MATCH && rcSearch!=DSLWB_RING_SEARCH_NO_MATCH) { FAPI_ERR("\tERROR : Getting delta ring from image was unsuccessful (rcSearch=%i).",rcSearch); FAPI_ERR("\tNo wiggle-flip programs will be stored in .rings section."); @@ -224,22 +230,20 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_RING_RETRIEVAL_ERROR); return rc; } - if (rcSearch==DSLWB_RING_SEARCH_MATCH || + if (rcSearch==DSLWB_RING_SEARCH_MATCH || rcSearch==DSLWB_RING_SEARCH_EXHAUST_MATCH) FAPI_DBG("\tRetrieving RS4 delta ring was successful."); // Check if we're done at this point. - // + // if (rcSearch==DSLWB_RING_SEARCH_NO_MATCH) { FAPI_INF("Wiggle-flip programming done."); FAPI_INF("Number of wf programs appended: %i", countWF); if (countWF==0) FAPI_INF("ZERO WF programs appended to .rings section."); sizeImageTmp = sizeImageOutMax; - rcLoc = append_empty_section( i_imageOut, - &sizeImageTmp, - SBE_XIP_SECTION_SLW, - SLW_SLW_SECTION_SIZE); + rcLoc = initialize_slw_section( i_imageOut, + &sizeImageTmp); if (rcLoc) { if (rcLoc==IMGBUILD_ERR_IMAGE_TOO_LARGE) { uint32_t & DATA_IMG_SIZE_OLD=sizeImageOld; @@ -253,14 +257,14 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, } return rc; } - FAPI_INF("SLW section allocated for Ramming table."); + FAPI_INF("SLW section allocated for Ramming and Scomming tables."); sbe_xip_image_size( i_imageOut, io_sizeImageOut); FAPI_INF("Final SLW image size: %i", *io_sizeImageOut); return FAPI_RC_SUCCESS; } - + deltaRingRS4 = (CompressedScanData*)rs4RingLayout.rs4Delta; - + FAPI_DBG("Dumping ring layout:"); FAPI_DBG("\tentryOffset = %i",(uint32_t)myRev64(rs4RingLayout.entryOffset)); FAPI_DBG("\tbackItemPtr = 0x%016llx",myRev64(rs4RingLayout.backItemPtr)); @@ -270,7 +274,7 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, FAPI_DBG("\tsysPhase = %i",rs4RingLayout.sysPhase); FAPI_DBG("\toverride = %i",rs4RingLayout.override); FAPI_DBG("\treserved1+2 = %i",rs4RingLayout.reserved1|rs4RingLayout.reserved2); - FAPI_DBG("\tRS4 magic # = 0x%08x",myRev32(deltaRingRS4->iv_magic)); + FAPI_DBG("\tRS4 magic # = 0x%08x",myRev32(deltaRingRS4->iv_magic)); FAPI_DBG("\tRS4 total size = %i",myRev32(deltaRingRS4->iv_size)); FAPI_DBG("\tUnXed data size = %i",myRev32(deltaRingRS4->iv_length)); FAPI_DBG("\tScan select = 0x%08x",myRev32(deltaRingRS4->iv_scanSelect)); @@ -303,20 +307,20 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, return rc; } FAPI_DBG("\tDecompression successful.\n"); - - ringByteLen = (ringBitLen-1)/8+1; - ringTrailBits = ringBitLen - 8*(ringByteLen-1); + +// ringByteLen = (ringBitLen-1)/8+1; +// ringTrailBits = ringBitLen - 8*(ringByteLen-1); // ========================================================================== // Create Wiggle-Flip Programs // ========================================================================== FAPI_DBG("--> Creating Wiggle-Flip Program."); - rcLoc = create_wiggle_flip_prg( (uint32_t*)deltaRingDxed, + rcLoc = create_wiggle_flip_prg( (uint32_t*)deltaRingDxed, ringBitLen, myRev32(deltaRingRS4->iv_scanSelect), (uint32_t)deltaRingRS4->iv_chipletId, - &wfInline, + &wfInline, &wfInlineLenInWords); if (rcLoc) { FAPI_ERR("ERROR : create_wiggle_flip_prg() failed w/rcLoc=%i",rcLoc); @@ -327,7 +331,7 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, return rc; } FAPI_DBG("\tWiggle-flip programming successful."); - + // ========================================================================== // Append Wiggle-Flip programs to .rings section. @@ -356,7 +360,7 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, return rc; } FAPI_DBG("\tUpdating image w/wiggle-flip program + header was successful."); - + // Update some variables for debugging and error reporting. sizeImageOld = sizeImageTmp; countWF++; @@ -367,8 +371,8 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, // ========================================================================== if (deltaRingDxed) free(deltaRingDxed); if (wfInline) free(wfInline); - - + + // ========================================================================== // Are we done? // ========================================================================== @@ -378,10 +382,8 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, if (countWF==0) FAPI_INF("ZERO WF programs appended to .rings section."); sizeImageTmp = sizeImageOutMax; - rcLoc = append_empty_section( i_imageOut, - &sizeImageTmp, - SBE_XIP_SECTION_SLW, - SLW_SLW_SECTION_SIZE); + rcLoc = initialize_slw_section( i_imageOut, + &sizeImageTmp); if (rcLoc) { if (rcLoc==IMGBUILD_ERR_IMAGE_TOO_LARGE) { uint32_t & DATA_IMG_SIZE_OLD=sizeImageOld; @@ -395,14 +397,14 @@ ReturnCode proc_slw_build( const fapi::Target &i_target, } return rc; } - FAPI_INF("SLW section allocated for Ramming table."); + FAPI_INF("SLW section allocated for Ramming and Scomming tables."); sbe_xip_image_size( i_imageOut, io_sizeImageOut); FAPI_INF("Final SLW image size: %i", *io_sizeImageOut); return FAPI_RC_SUCCESS; } FAPI_DBG("nextRing (at bottom)=0x%016llx",(uint64_t)nextRing); - + } while (nextRing!=NULL); /*************************************************************************** * SEARCH LOOP - End * diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.H b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.H index 7db527191..be6d8db06 100644 --- a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.H +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.H @@ -23,8 +23,6 @@ */ #include <fapi.H> -#include "p8_delta_scan_rw.h" -#include "p8_pore_table_gen_api.H" typedef fapi::ReturnCode (*proc_slw_build_FP_t) ( const fapi::Target&, const void*, diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build_errors.xml b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build_errors.xml index e579245df..9066290f4 100644 --- a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build_errors.xml +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build_errors.xml @@ -102,7 +102,7 @@ <!-- *********************************************************************** --> <hwpError> <rc>RC_PROC_SLWB_UNKOWN_ERROR</rc> - <description>Unknown error, shouldn't be in this code section.</description> + <description>Unknown error. (Shouldn't be in this code section.)</description> <ffdc>RC_LOCAL</ffdc> </hwpError> </hwpErrors> diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.c b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.c index 722e8fdb7..138b1d7cb 100644 --- a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.c +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.c @@ -21,7 +21,7 @@ * * IBM_PROLOG_END_TAG */ -// $Id: sbe_xip_image.c,v 1.17 2012/05/22 22:59:05 bcbrock Exp $ +// $Id: sbe_xip_image.c,v 1.20 2012/06/21 01:41:31 bcbrock Exp $ // $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/sbe/sbe_xip_image.c,v $ //----------------------------------------------------------------------------- // *! (C) Copyright International Business Machines Corp. 2011 @@ -192,6 +192,27 @@ dumpSectionTable(const void* i_image) // endian-conversion routines rather than counting on a system-specific header // to provide these. +/// Byte-reverse a 16-bit integer if on a little-endian machine + +static uint16_t +revle16(const uint16_t i_x) +{ + uint16_t rx; + +#ifndef _BIG_ENDIAN + uint8_t *pix = (uint8_t*)(&i_x); + uint8_t *prx = (uint8_t*)(&rx); + + prx[0] = pix[1]; + prx[1] = pix[0]; +#else + rx = i_x; +#endif + + return rx; +} + + /// Byte-reverse a 32-bit integer if on a little-endian machine static uint32_t @@ -421,8 +442,8 @@ translateSection(SbeXipSection* o_dest, const SbeXipSection* i_src) { #ifndef _BIG_ENDIAN -#if SBE_XIP_HEADER_VERSION != 7 -#error This code assumes the SBE-XIP header version 7 layout +#if SBE_XIP_HEADER_VERSION != 8 +#error This code assumes the SBE-XIP header version 8 layout #endif o_dest->iv_offset = revle32(i_src->iv_offset); @@ -446,8 +467,8 @@ translateToc(SbeXipToc* o_dest, SbeXipToc* i_src) { #ifndef _BIG_ENDIAN -#if SBE_XIP_HEADER_VERSION != 7 -#error This code assumes the SBE-XIP header version 7 layout +#if SBE_XIP_HEADER_VERSION != 8 +#error This code assumes the SBE-XIP header version 8 layout #endif o_dest->iv_id = revle32(i_src->iv_id); @@ -476,6 +497,7 @@ finalSection(const void* i_image, int* o_sectionId) sbe_xip_translate_header(&hostHeader, (SbeXipHeader*)i_image); offset = 0; + *o_sectionId = 0; /* Make GCC -O3 happy */ for (i = 0; i < SBE_XIP_SECTIONS; i++) { if (hostHeader.iv_section[i].iv_offset > offset) { *o_sectionId = i; @@ -835,7 +857,36 @@ validateTocEntry(void* io_image, const SbeXipItem* i_item, void* io_arg) } -/// Normalize a TOC entry +// This is the FNV-1a hash, used for hashing symbol names in the .fixed +// section into 32-bit hashes for the mini-TOC. + +// According to the authors: + +// "FNV hash algorithms and source code have been released into the public +// domain. The authors of the FNV algorithmm look deliberate steps to disclose +// the algorhtm (sic) in a public forum soon after it was invented. More than +// a year passed after this public disclosure and the authors deliberatly took +// no steps to patent the FNV algorithm. Therefore it is safe to say that the +// FNV authors have no patent claims on the FNV algorithm as published." + +#define FNV_OFFSET_BASIS 2166136261u +#define FNV_PRIME32 16777619u + +uint32_t +hash32(const char* s) +{ + uint32_t hash; + + hash = FNV_OFFSET_BASIS; + while (*s) { + hash ^= *s++; + hash *= FNV_PRIME32; + } + return hash; +} + + +// Normalize a TOC entry // Normalize the TOC entry by converting relocatable pointers into 32-bit // offsets from the beginning of the section containing the data. All @@ -843,11 +894,14 @@ validateTocEntry(void* io_image, const SbeXipItem* i_item, void* io_arg) // in bits 16:31 of the link address of the image. static int -normalizeToc(void* io_image, SbeXipToc *io_imageToc) +normalizeToc(void* io_image, SbeXipToc *io_imageToc, + SbeXipHashedToc** io_fixedTocEntry, + size_t* io_fixedEntriesRemaining) { SbeXipToc hostToc; int idSection, dataSection; uint32_t idOffset, dataOffset; + char* hostString; int rc; do { @@ -858,6 +912,9 @@ normalizeToc(void* io_image, SbeXipToc *io_imageToc) translateToc(&hostToc, io_imageToc); + hostString = + (char*)pore2Host(io_image, fullAddress(io_image, hostToc.iv_id)); + rc = pore2Section(io_image, fullAddress(io_image, hostToc.iv_id), &idSection, @@ -882,6 +939,30 @@ normalizeToc(void* io_image, SbeXipToc *io_imageToc) hostToc.iv_data = dataOffset; hostToc.iv_section = dataSection; + // If this TOC entry is from .fixed, create a new record in .fixed_toc + + if (hostToc.iv_section == SBE_XIP_SECTION_FIXED) { + + if (*io_fixedEntriesRemaining == 0) { + rc = TRACE_ERRORX(SBE_XIP_TOC_ERROR, + "Too many TOC entries for .fixed\n"); + break; + } + if (hostToc.iv_data != (uint16_t)hostToc.iv_data) { + rc = TRACE_ERRORX(SBE_XIP_IMAGE_ERROR, + "The .fixed section is too big to index\n"); + break; + } + + (*io_fixedTocEntry)->iv_hash = revle32(hash32(hostString)); + (*io_fixedTocEntry)->iv_offset = revle16(hostToc.iv_data); + (*io_fixedTocEntry)->iv_type = hostToc.iv_type; + (*io_fixedTocEntry)->iv_elements = hostToc.iv_elements; + + (*io_fixedTocEntry)++; + (*io_fixedEntriesRemaining)--; + } + // Finally update the TOC entry translateToc(io_imageToc, &hostToc); @@ -892,6 +973,33 @@ normalizeToc(void* io_image, SbeXipToc *io_imageToc) } +// Check for hash collisions in the .fixed mini-TOC. Note that endianness is +// not an issue here, as we're comparing for equality. + +static int +hashCollision(SbeXipHashedToc* i_fixedToc, size_t i_entries) +{ + int rc; + size_t i, j; + + rc = 0; + + for (i = 0; i < i_entries; i++) { + for (j = i + 1; j < i_entries; j++) { + if (i_fixedToc[i].iv_hash == i_fixedToc[j].iv_hash) { + rc = TRACE_ERRORX(SBE_XIP_HASH_COLLISION, + "Hash collision at index %d\n", + i); + break; + } + } + if (rc) break; + } + + return rc; +} + + /// Decode a normalized image-format TOC entry into a host-format SbeXipItem /// structure @@ -945,6 +1053,8 @@ decodeToc(void* i_image, o_item->iv_address = linkAddress(i_image) + dataSection.iv_offset + hostToc.iv_data; + + o_item->iv_partial = 0; } while (0); return rc; @@ -1020,6 +1130,92 @@ padImage(void* io_image, uint32_t i_allocation, } +// Get the .fixed_toc section + +static int +getFixedToc(void* io_image, + SbeXipHashedToc** o_imageToc, + size_t* o_entries) +{ + int rc; + SbeXipSection section; + + rc = sbe_xip_get_section(io_image, SBE_XIP_SECTION_FIXED_TOC, §ion); + if (!rc) { + + *o_imageToc = + (SbeXipHashedToc*)((unsigned long)io_image + section.iv_offset); + + *o_entries = section.iv_size / sizeof(SbeXipHashedToc); + } + + return rc; +} + + +// Search for an item in the fixed TOC, and populate a partial TOC entry if +// requested. This table is small and unsorted so a linear search is +// adequate. The TOC structures are also small so all byte-reversal is done +// 'by hand' rather than with a translate-type API. + +static int +fixedFind(void* i_image, const char* i_id, SbeXipItem* o_item) +{ + int rc; + SbeXipHashedToc* toc; + size_t entries; + uint32_t hash; + SbeXipSection fixedSection; + uint32_t offset; + + do { + rc = getFixedToc(i_image, &toc, &entries); + if (rc) break; + + for (hash = revle32(hash32(i_id)); entries != 0; entries--, toc++) { + if (toc->iv_hash == hash) break; + } + + if (entries == 0) { + rc = SBE_XIP_ITEM_NOT_FOUND; + break; + } else { + rc = 0; + } + + // The caller may have requested a lookup only (o_item == 0), in which + // case we're done. Otherwise we create a partial SbeXipItem and + // populate the non-0 fields analogously to the decodeToc() + // routine. The data resides in the .fixed section in this case. + + if (o_item == 0) break; + + o_item->iv_partial = 1; + o_item->iv_toc = 0; + o_item->iv_id = 0; + + o_item->iv_type = toc->iv_type; + o_item->iv_elements = toc->iv_elements; + + rc = sbe_xip_get_section(i_image, SBE_XIP_SECTION_FIXED, &fixedSection); + if (rc) break; + + if (fixedSection.iv_size == 0) { + rc = TRACE_ERROR(SBE_XIP_DATA_NOT_PRESENT); + break; + } + + offset = fixedSection.iv_offset + revle16(toc->iv_offset); + + o_item->iv_imageData = (void*)((uint8_t*)i_image + offset); + o_item->iv_address = linkAddress(i_image) + offset; + + } while (0); + + return rc; +} + + //////////////////////////////////////////////////////////////////////////// // Published API //////////////////////////////////////////////////////////////////////////// @@ -1054,6 +1250,14 @@ sbe_xip_validate(void* i_image, const uint32_t i_size) break; } + if (sizeof(SbeXipHashedToc) != SIZE_OF_SBE_XIP_HASHED_TOC) { + rc = TRACE_ERRORX(SBE_XIP_BUG, + "C/Assembler size mismatch(%d/%d) " + "for SbeXipHashedToc\n", + sizeof(SbeXipHashedToc), SIZE_OF_SBE_XIP_HASHED_TOC); + break; + } + // Validate the image pointer and magic number rc = quickCheck(i_image, 0); @@ -1160,20 +1364,41 @@ sbe_xip_normalize(void* io_image) int rc, i; SbeXipSection section; SbeXipToc* imageToc; - size_t entries; + SbeXipHashedToc* fixedImageToc; + SbeXipHashedToc* fixedTocEntry; + size_t tocEntries, fixedTocEntries, fixedEntriesRemaining; do { rc = quickCheck(io_image, 0); if (rc) break; if (!normalized(io_image)) { - rc = getToc(io_image, &imageToc, &entries, 0, 0); + + rc = getToc(io_image, &imageToc, &tocEntries, 0, 0); if (rc) break; - for (; entries--; imageToc++) { - rc = normalizeToc(io_image, imageToc); - if (rc) break; + + rc = getFixedToc(io_image, &fixedImageToc, &fixedTocEntries); + if (rc) break; + + fixedTocEntry = fixedImageToc; + fixedEntriesRemaining = fixedTocEntries; + + for (; tocEntries--; imageToc++) { + rc = normalizeToc(io_image, imageToc, + &fixedTocEntry, &fixedEntriesRemaining); + + } + if (rc) break; + + if (fixedEntriesRemaining != 0) { + rc = TRACE_ERRORX(SBE_XIP_TOC_ERROR, + "Not enough TOC entries for .fixed"); + break; } + + rc = hashCollision(fixedImageToc, fixedTocEntries); if (rc) break; + ((SbeXipHeader*)io_image)->iv_normalized = 1; } @@ -1228,6 +1453,9 @@ sbe_xip_get_section(const void* i_image, } +// If the 'big' TOC is not present, search the mini-TOC that only indexes the +// fixed section. + int sbe_xip_find(void* i_image, const char* i_id, @@ -1236,11 +1464,20 @@ sbe_xip_find(void* i_image, int rc; SbeXipToc* toc; SbeXipItem item, *pitem; + SbeXipSection* tocSection; do { rc = quickCheck(i_image, 1); if (rc) break; + rc = getSectionPointer(i_image, SBE_XIP_SECTION_TOC, &tocSection); + if (rc) break; + + if (tocSection->iv_size == 0) { + rc = fixedFind(i_image, i_id, o_item); + break; + } + if (sorted(i_image)) { rc = binarySearch(i_image, i_id, &toc); } else { @@ -1920,8 +2157,8 @@ sbe_xip_translate_header(SbeXipHeader* o_dest, const SbeXipHeader* i_src) SbeXipSection* destSection; const SbeXipSection* srcSection; -#if SBE_XIP_HEADER_VERSION != 7 -#error This code assumes the SBE-XIP header version 7 layout +#if SBE_XIP_HEADER_VERSION != 8 +#error This code assumes the SBE-XIP header version 8 layout #endif o_dest->iv_magic = revle64(i_src->iv_magic); diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.h b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.h index 081f368e8..02421cd30 100644 --- a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.h +++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.h @@ -24,7 +24,7 @@ #ifndef __SBE_XIP_IMAGE_H #define __SBE_XIP_IMAGE_H -// $Id: sbe_xip_image.h,v 1.15 2012/05/22 03:26:27 bcbrock Exp $ +// $Id: sbe_xip_image.h,v 1.18 2012/07/06 20:03:09 bcbrock Exp $ // $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/sbe/sbe_xip_image.h,v $ //----------------------------------------------------------------------------- // *! (C) Copyright International Business Machines Corp. 2011 @@ -45,7 +45,7 @@ /// If any changes are made to this file or to sbe_xip_header.H, please update /// the header version and follow-up on all of the error messages. -#define SBE_XIP_HEADER_VERSION 7 +#define SBE_XIP_HEADER_VERSION 8 /// \defgroup sbe_xip_magic_numbers SBE-XIP magic numbers /// @@ -79,18 +79,18 @@ #define SBE_XIP_SECTION_HEADER 0 #define SBE_XIP_SECTION_FIXED 1 -#define SBE_XIP_SECTION_IPL_TEXT 2 -#define SBE_XIP_SECTION_IPL_DATA 3 -#define SBE_XIP_SECTION_TEXT 4 -#define SBE_XIP_SECTION_DATA 5 -#define SBE_XIP_SECTION_TOC 6 -#define SBE_XIP_SECTION_STRINGS 7 -#define SBE_XIP_SECTION_PIBMEM0 8 -#define SBE_XIP_SECTION_PIBMEM1 9 -#define SBE_XIP_SECTION_RINGS 10 -#define SBE_XIP_SECTION_HALT 11 -#define SBE_XIP_SECTION_SLW 12 -#define SBE_XIP_SECTION_RESERVED_2 13 +#define SBE_XIP_SECTION_FIXED_TOC 2 +#define SBE_XIP_SECTION_IPL_TEXT 3 +#define SBE_XIP_SECTION_IPL_DATA 4 +#define SBE_XIP_SECTION_TEXT 5 +#define SBE_XIP_SECTION_DATA 6 +#define SBE_XIP_SECTION_TOC 7 +#define SBE_XIP_SECTION_STRINGS 8 +#define SBE_XIP_SECTION_HALT 9 +#define SBE_XIP_SECTION_PIBMEM0 10 +#define SBE_XIP_SECTION_PIBMEM1 11 +#define SBE_XIP_SECTION_RINGS 12 +#define SBE_XIP_SECTION_SLW 13 #define SBE_XIP_SECTION_RESERVED_1 14 #define SBE_XIP_SECTION_RESERVED_0 15 @@ -105,18 +105,18 @@ const char* var[] = { \ ".header", \ ".fixed", \ + ".fixed_toc", \ ".ipl_text", \ ".ipl_data", \ ".text", \ ".data", \ ".toc", \ ".strings", \ + ".halt", \ ".pibmem0", \ ".pibmem1", \ ".rings", \ - ".halt", \ ".slw", \ - ".reserved_2", \ ".reserved_1", \ ".reserved_0" \ } @@ -134,7 +134,7 @@ /// Maximum section alignment for SBE-XIP sections #define SBE_XIP_MAX_SECTION_ALIGNMENT 128 -/// defgroup sbe_xip_toc_types SBE-XIP Table of Contents data types +/// \defgroup sbe_xip_toc_types SBE-XIP Table of Contents data types /// /// These are the data types stored in the \a iv_type field of the SbeXipToc /// objects. These must be defined as manifest constants because they are @@ -446,19 +446,70 @@ typedef struct { #define SIZE_OF_SBE_XIP_TOC 12 +/// A C-structure form of hashed SBE-XIP Table of Contents (TOC) entries +/// +/// This structure was introduced in order to allow a small TOC for the .fixed +/// section to support minimum-sized SEEPROM images in which the global TOC +/// and all strings have been stripped out. In this structure the index +/// string has been replaced by a 32-bit hash, and there is no longer a record +/// of the original data name other then the hash. The section of the data is +/// assumed to be .fixed, with a maximum 16-bit offset. +/// +/// These structures are created when entries are made in the .fixed section. +/// They are created empty, then filled in during image normalization. +/// +/// This structure allows the sbe_xip_get*() and sbe_xip_set*() APIs to work +/// even on highly-stripped SEEPROM images. + +typedef struct { + + /// A 32-bit hash (FNV-1a) of the Id string. + uint32_t iv_hash; + + /// The offset in bytes from the start of the (implied) section of the data + uint16_t iv_offset; + + /// The type of the data; See \ref sbe_xip_toc_types. + uint8_t iv_type; + + /// The number of elements for vector types, otherwise 1 for scalar types + /// and addresses. + /// + /// Vectors are naturally limited in size, e.g. to the number of cores, + /// chips in a node, DD-levels etc. If \a iv_elements is 0 then no bounds + /// checking is done on get/set accesses of the data. + uint8_t iv_elements; + +} SbeXipHashedToc; + +/// The SbeXipHashedToc structure is created by assembler code and is expected +/// to have the same size in C code. This constraint is checked in +/// sbe_xip_validate(). +#define SIZE_OF_SBE_XIP_HASHED_TOC 8 + + /// A decoded TOC entry for use by applications /// /// This structure is a decoded form of a normalized TOC entry, filled in by /// the sbe_xip_decode_toc() and sbe_xip_find() APIs. This structure is -/// always returned with data elements in host-endian format. +/// always returned with data elements in host-endian format. +/// +/// In the event that the TOC has been removed from the image, this structure +/// will also be returned by sbe_xip_find() with information populated from +/// the .fixed_toc section if possible. In this case the field \a iv_partial +/// will be set and only the fields \a iv_address, \a iv_imageData, \a iv_type +/// and \a iv_elements will be populated (all other fields will be set to 0). /// /// \note Only special-purpose applications will ever need to use this /// structure given that the higher-level APIs sbe_xip_get_*() and -/// sbe_xip_set_*() are provided and shoudl be used if possible. +/// sbe_xip_set_*() are provided and should be used if possible, especially +/// given that the information may be truncated as described above. typedef struct { /// A pointer to the associated TOC entry as it exists in the image + /// + /// If \a iv_partial is set this field is returned as 0. SbeXipToc* iv_toc; /// The full relocatable PORE address @@ -466,7 +517,7 @@ typedef struct { /// All relocatable addresses are computed from the \a iv_linkAddress /// stored in the header. For scalar and string data, this is the /// relocatable address of the data. For address-only entries, this is - /// the indexed address itself. + /// the indexed address itself. uint64_t iv_address; /// A host pointer to the first byte of text or data within the image @@ -483,7 +534,8 @@ typedef struct { /// /// This is a pointer in host memory to a string that names the TOC entry /// requested. This field is set to a pointer to the ID string of the TOC - /// entry inside the image. + /// entry inside the image. If \a iv_partial is set this field is returned + /// as 0. char* iv_id; /// The data type, one of the SBE_XIP_* constants @@ -497,6 +549,13 @@ typedef struct { /// used to bounds check indexed accesses. uint8_t iv_elements; + /// Is this record only partially populated? + /// + /// This field is set to 0 normally, and only set to 1 if a lookup is made + /// in an image that only has the fixed TOC and the requested Id hashes to + /// the fixed TOC. + uint8_t iv_partial; + } SbeXipItem; @@ -800,7 +859,7 @@ sbe_xip_set_element(void *i_image, /// Set string data in an SBE-XIP image /// -/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The +/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory. The /// image is assumed to be consistent with the information contained in the /// header regarding the presence of and sizes of all sections. The image is /// also required to have been normalized. @@ -882,7 +941,7 @@ sbe_xip_write_uint64(void *io_image, /// \retval 0 Success; All TOC entries were mapped, including the case that /// the .toc section is empty. /// -/// \revtal non-0 May be either one of the SBE-XIP image error codes (see \ref +/// \retval non-0 May be either one of the SBE-XIP image error codes (see \ref /// sbe_xip_image_errors), or a non-zero code from \a i_fn. Since the standard /// SBE_XIP return codes are > 0, application-defined codes should be < 0. int @@ -920,9 +979,16 @@ sbe_xip_map_toc(void* io_image, /// - SBE_XIP_DATA_NOT_PRESENT : The item appears in the TOC, however the /// section containing the data is no longer present in the image. /// -/// \note This API should not be used unless absolutely necessary. To obtain -/// data from the image or update data in the image use the sbe_xip_get_*() -/// and sbe_xip_set_*() APIs respectively whenever possible. +/// If the TOC section has been deleted from the image, then the search is +/// restricted to the abbreviated TOC that indexes data in the .fixed section. +/// In this case the \a o_item structure is marked with a 1 in the \a +/// iv_partial field since the abbreviated TOC can not populate the entire +/// SbeXipItem structure. +/// +/// \note This API should typically only be used as a predicate, not as a way +/// to access the image via the returned SbeXipItem structure. To obtain data +/// from the image or update data in the image use the sbe_xip_get_*() and +/// sbe_xip_set_*() APIs respectively. /// /// \retval 0 Success /// @@ -948,6 +1014,8 @@ sbe_xip_find(void* i_image, /// const char* i_rcString, /// void* io_arg) /// +/// \endcode +/// /// \param[in,out] io_arg The private argument of \a i_fn. /// /// This API iterates over each entry of the .halt section, calling \a i_fn @@ -959,10 +1027,10 @@ sbe_xip_find(void* i_image, /// /// \retval 0 Success, including the case that the image has no .halt section. /// -/// \revtal non-0 May be either one of the SBE-XIP image error codes (see \ref +/// \retval non-0 May be either one of the SBE-XIP image error codes (see \ref /// sbe_xip_image_errors), or any non-zero code from \a i_fn. Since the -/// standard SBE_XIP return codes are > 0, application-defined codes should be -/// < 0. +/// standard SBE_XIP return codes are \> 0, application-defined codes should +/// be \< 0. int sbe_xip_map_halt(void* io_image, int (*i_fn)(void* io_image, @@ -989,19 +1057,19 @@ sbe_xip_map_halt(void* io_image, /// /// \retval 0 Success /// -/// \retval SBE_XIP_ITEM_NOT_FOUND The \a i_poreAddress is not associated +/// \revtal SBE_XIP_ITEM_NOT_FOUND The \a i_poreAddress is not associated /// with a halt code in .halt. /// /// \revtal Other See \ref sbe_xip_image_errors int sbe_xip_get_halt(void* io_image, - const uint64_t i_poreAdress, + const uint64_t i_poreAddress, const char** o_rcString); /// Delete a section from an SBE-XIP image in host memory /// -/// \param[in,out] i_image A pointer to an SBE-XIP image in host memory. The +/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory. The /// image is assumed to be consistent with the information contained in the /// header regarding the presence of and sizes of all sections. The image is /// also required to have been normalized. @@ -1041,10 +1109,10 @@ sbe_xip_delete_section(void* io_image, const int i_sectionId); /// section. /// /// This API creates a bytewise duplicate of a non-empty section into newly -/// malloc()-ed memory. At exit \a o_duplicate points to the duplicate, and \i +/// malloc()-ed memory. At exit \a o_duplicate points to the duplicate, and \a /// o_size is set the the size of the duplicated section. The caller is /// responsible for free()-ing the memory when no longer required. The -/// pointer at \o_duplicate is set to NULL (0) and teh \a o_size is set to 0 +/// pointer at \a o_duplicate is set to NULL (0) and the \a o_size is set to 0 /// in the event of any failure. /// /// \retval 0 Success @@ -1054,7 +1122,7 @@ int sbe_xip_duplicate_section(const void* i_image, const int i_sectionId, void** o_duplicate, - uint32_t* size); + uint32_t* o_size); /// Append binary data to an SBE-XIP image held in host memory @@ -1251,7 +1319,7 @@ sbe_xip_pore2section(const void* i_image, int sbe_xip_host2pore(const void* i_image, void* i_hostAddress, - uint64_t* i_poreAddress); + uint64_t* o_poreAddress); /// \defgroup sbe_xip_image_errors Error codes from SBE-XIP image APIs @@ -1285,7 +1353,7 @@ sbe_xip_host2pore(const void* i_image, /// A data type mismatch or an illegal type was specified or implied for an /// operation. -#define SBE_XIP_TYPE_ERROR 8 +#define SBE_XIP_TYPE_ERROR 7 /// A bug in an SBE-XIP image API #define SBE_XIP_BUG 8 @@ -1318,6 +1386,9 @@ sbe_xip_host2pore(const void* i_image, /// Error associated with the disassembler occured. #define SBE_XIP_DISASSEMBLER_ERROR 15 +/// hash collision creating the .fixed_toc section +#define SBE_XIP_HASH_COLLISION 16 + /// Applications can expand this macro to declare an array of string forms of /// the error codes if desired. #define SBE_XIP_ERROR_STRINGS(var) \ @@ -1338,6 +1409,7 @@ sbe_xip_host2pore(const void* i_image, "SBE_XIP_BOUNDS_ERROR", \ "SBE_XIP_WOULD_OVERFLOW", \ "SBE_XIP_DISASSEMBLER_ERROR", \ + "SBE_XIP_HASH_COLLISION", \ } /// Applications can use this macro to safely index the array of error diff --git a/src/usr/hwpf/hwp/core_activate/core_activate.C b/src/usr/hwpf/hwp/core_activate/core_activate.C index e4ecf4ba1..e3d5596af 100644 --- a/src/usr/hwpf/hwp/core_activate/core_activate.C +++ b/src/usr/hwpf/hwp/core_activate/core_activate.C @@ -71,56 +71,143 @@ using namespace fapi; using namespace ISTEP; + // // Wrapper function to call 16.1 : // host_activate_master // -void call_host_activate_master( void *io_pArgs ) -{ - errlHndl_t l_errl = NULL; + void call_host_activate_master( void *io_pArgs ) + { + errlHndl_t l_errl = NULL; - TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, - "call_host_activate_master entry" ); + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "call_host_activate_master entry" ); -#if 0 - // @@@@@ CUSTOM BLOCK: @@@@@ - // figure out what targets we need - // customize any other inputs - // set up loops to go through all targets (if parallel, spin off a task) - - // dump physical path to targets - EntityPath l_path; - l_path = l_@targetN_target->getAttr<ATTR_PHYS_PATH>(); - l_path.dump(); - - // cast OUR type of target to a FAPI type of target. - const fapi::Target l_fapi_@targetN_target( - TARGET_TYPE_MEMBUF_CHIP, - reinterpret_cast<void *> - (const_cast<TARGETING::Target*>(l_@targetN_target)) ); - - // call the HWP with each fapi::Target - FAPI_INVOKE_HWP( l_errl, host_activate_master, _args_...); - if ( l_errl ) - { - TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, - "ERROR : .........." ); - errlCommit( l_errl, HWPF_COMP_ID ); - } - else - { - TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, - "SUCCESS : .........." ); - } - // @@@@@ END CUSTOM BLOCK: @@@@@ + // @@@@@ CUSTOM BLOCK: @@@@@ + + do { + + // find the master core, i.e. the one we are running on + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "call_host_activate_master: Find master core: " ); + + const TARGETING::Target* l_masterCore = getMasterCore( ); + assert( l_masterCore != NULL ); + + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "call_host_activate_master: Find master chip: " ); + TARGETING::Target* l_cpu_target = const_cast<TARGETING::Target *> + ( getParentChip( l_masterCore ) ); + + // dump physical path to target + EntityPath l_path; + l_path = l_cpu_target->getAttr<ATTR_PHYS_PATH>(); + l_path.dump(); + + // cast OUR type of target to a FAPI type of target. + const fapi::Target l_fapi_cpu_target( + TARGET_TYPE_PROC_CHIP, + reinterpret_cast<void *> + (const_cast<TARGETING::Target*>(l_cpu_target)) ); + + +#if 1 + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Call proc_prep_master_winkle when integrated..." ); +#else + // call the HWP with each fapi::Target + FAPI_INVOKE_HWP( l_errl, + proc_prep_master_winkle, + l_fapi_cpu_target ); #endif + if ( l_errl ) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "proc_prep_master_winkle ERROR : Returning errorlog, PLID=0x%x", + l_errl->plid() ); + break; + } + else + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "proc_prep_master_winkle SUCCESS" ); + } - TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, - "call_host_activate_master exit" ); + // put the master into winkle. + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "call_host_activate_master: put master into winkle..." ); - // end task, returning any errorlogs to IStepDisp - task_end2( l_errl ); -} + // @todo 2012-07-30 currently this is just a stub... + int l_rc = cpu_master_winkle( ); + if ( l_rc ) + { + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, + "ERROR : failed to winkle master, rc=0x%x", + l_rc ); + /*@ + * @errortype + * @reasoncode ISTEP_FAIL_MASTER_WINKLE_RC + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid ISTEP_CORE_ACTIVATE + * @userdata1 return code from cpu_master_winkle + * + * @devdesc p8_pore_gen_cpureg returned an error when + * attempting to change a reg value in the PORE image. + */ + l_errl = + new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + ISTEP_CORE_ACTIVATE, + ISTEP_FAIL_MASTER_WINKLE_RC, + l_rc ); + break; + } + + + // -------------------------------------------------------- + // $$ @todo do something to trigger IPI at this point. + // MAGIC_INSTRUCTION( ???? ); + // -------------------------------------------------------- + + + // -------------------------------------------------------- + // should return from Winkle at this point + // -------------------------------------------------------- + + +#if 1 + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Call proc_stop_deadman_timer when integrated..." ); +#else + // call the HWP with each fapi::Target + FAPI_INVOKE_HWP( l_errl, + proc_stop_deadman_timer, + l_fapi_cpu_target ); +#endif + if ( l_errl ) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "proc_stop_deadman_timer ERROR : Returning errorlog, PLID=0x%x", + l_errl->plid() ); + break; + } + else + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "proc_prep_master_winkle SUCCESS" ); + } + + } while ( 0 ); + + // @@@@@ END CUSTOM BLOCK: @@@@@ + + + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "call_host_activate_master exit" ); + + // end task, returning any errorlogs to IStepDisp + task_end2( l_errl ); + + } diff --git a/src/usr/hwpf/makefile b/src/usr/hwpf/makefile index 8b58435fa..99b51dd3f 100644 --- a/src/usr/hwpf/makefile +++ b/src/usr/hwpf/makefile @@ -41,7 +41,9 @@ HWP_ERROR_XML_FILES = hwp/fapiHwpErrorInfo.xml \ hwp/mvpd_errors.xml \ ../pore/fapiporeve/fapiPoreVe_errors.xml \ hwp/dram_initialization/proc_setup_bars/proc_setup_bars_errors.xml \ - hwp/dram_initialization/proc_setup_bars/proc_fab_smp_errors.xml + hwp/dram_initialization/proc_setup_bars/proc_fab_smp_errors.xml \ + hwp/build_winkle_images/proc_set_pore_bar/proc_set_pore_bar_errors.xml \ + hwp/build_winkle_images/proc_pba_bar_config/proc_pba_bar_config_errors.xml diff --git a/src/usr/pnor/pnordd.C b/src/usr/pnor/pnordd.C index 2468b470d..4801e07a2 100644 --- a/src/usr/pnor/pnordd.C +++ b/src/usr/pnor/pnordd.C @@ -1404,9 +1404,19 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address) This code is used in the MODEL_MEMCPY and MODEL_LPC_MEM modes */ -#define FAKE_PNOR_START 4*MEGABYTE +// $$ #define FAKE_PNOR_START 4*MEGABYTE +// $$ #define FAKE_PNOR_END 8*MEGABYTE +// $$ #define FAKE_PNOR_SIZE 4*MEGABYTE +// +// @note fake pnor is moved up and shrunk by 1/2 meg to make room for +// the SLW image, it must be at a 1 M boundary. +// See build_winkle_images for more info. +// +#define FAKE_PNOR_START 4*MEGABYTE+5*KILOBYTE #define FAKE_PNOR_END 8*MEGABYTE -#define FAKE_PNOR_SIZE 4*MEGABYTE +#define FAKE_PNOR_SIZE 3*MEGABYTE + + void write_fake_pnor( uint64_t i_pnorAddr, void* i_buffer, size_t i_size ) { //create a pointer to the offset start. diff --git a/src/usr/targeting/common/utilFilter.C b/src/usr/targeting/common/utilFilter.C index f6fcc3756..20acaf170 100644 --- a/src/usr/targeting/common/utilFilter.C +++ b/src/usr/targeting/common/utilFilter.C @@ -32,6 +32,8 @@ #include <targeting/common/predicates/predicateisfunctional.H> #include <targeting/common/predicates/predicatepostfixexpr.H> +#include <sys/task.h> // task_getcpuid() + /** * Miscellaneous Filter Utility Functions @@ -209,4 +211,56 @@ const Target * getParentChip( const Target * i_pChiplet ) return l_pChip; } -}; + +const TARGETING::Target * getMasterCore( ) +{ + uint64_t l_masterCoreID = task_getcpuid() & ~7; + const TARGETING::Target * l_masterCore = NULL; + + TARGETING::Target * l_processor = NULL; + (void)TARGETING::targetService().masterProcChipTargetHandle( l_processor ); + FABRIC_NODE_ID_ATTR l_logicalNodeId = + l_processor->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>(); + FABRIC_CHIP_ID_ATTR l_chipId = + l_processor->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>(); + + TargetHandleList l_cores; + getChildChiplets( l_cores, + l_processor, + TYPE_CORE, + true ); + + TRACDCOMP( g_trac_targeting, + "getMasterCore: found %d cores on master proc", + l_cores.size() ); + + for ( uint8_t l_coreNum=0; l_coreNum < l_cores.size(); l_coreNum++ ) + { + TARGETING::Target * l_core = l_cores[ l_coreNum ] ; + + CHIP_UNIT_ATTR l_coreId = + l_core->getAttr<TARGETING::ATTR_CHIP_UNIT>(); + + uint64_t pir = l_coreId << 3; + pir |= l_chipId << 7; + pir |= l_logicalNodeId << 10; + + if (pir == l_masterCoreID){ + TRACDCOMP( g_trac_targeting, + "found master core: 0x%x, PIR=0x%x :", + l_coreId, + pir ); + EntityPath l_path; + l_path = l_core->getAttr<ATTR_PHYS_PATH>(); + l_path.dump(); + + l_masterCore = l_core ; + break; + } + + } // endfor + + return l_masterCore; +} + +}; // end namespace diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml index 6626b2906..a032aaaf9 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml @@ -4011,4 +4011,32 @@ </hwpfToHbAttrMap> </attribute> +<attribute> + <id>SLW_IMAGE_ADDR</id> + <description> + Location of runtime winkle image for this processor chip. + Written by host_build_winkle (istep 15.1) + </description> + <simpleType> + <uint64_t></uint64_t> + </simpleType> + <persistency>volatile-zeroed</persistency> + <readable/> + <writeable/> +</attribute> + +<attribute> + <id>SLW_IMAGE_SIZE</id> + <description> + Size of runtime winkle image for this processor chip. + Written by host_build_winkle (istep 15.1) + </description> + <simpleType> + <uint64_t></uint64_t> + </simpleType> + <persistency>volatile-zeroed</persistency> + <readable/> + <writeable/> +</attribute> + </attributes> diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml index ba3bce39d..7be57fcef 100644 --- a/src/usr/targeting/common/xmltohb/target_types.xml +++ b/src/usr/targeting/common/xmltohb/target_types.xml @@ -204,7 +204,9 @@ <!-- proc_fab_smp_fabric_attributes.xml --> <attribute><id>FREQ_CORE</id></attribute> <attribute><id>PROC_PCIE_NOT_F_LINK</id></attribute> - + <!-- new attribute for isteps 15 & 16 --> + <attribute><id>SLW_IMAGE_ADDR</id></attribute> + <attribute><id>SLW_IMAGE_SIZE</id></attribute> </targetType> <targetType> |