From 98947f1f7f8094304fd6ac2e8a9bdd21b449900a Mon Sep 17 00:00:00 2001 From: vanlee Date: Tue, 19 Mar 2013 23:55:00 -0500 Subject: HWP: Integrate cen_xip_customize into hostboot Change-Id: Ib4098f329d94b5b7138e311b9a6393a69d716239 RTC: 64603 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/3603 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III --- .../p8_slw_build/p8_pore_table_gen_api_fixed.C | 747 +++++++++++++++++++++ 1 file changed, 747 insertions(+) create mode 100644 src/usr/hwpf/hwp/build_winkle_images/p8_slw_build/p8_pore_table_gen_api_fixed.C (limited to 'src/usr/hwpf/hwp/build_winkle_images/p8_slw_build/p8_pore_table_gen_api_fixed.C') diff --git a/src/usr/hwpf/hwp/build_winkle_images/p8_slw_build/p8_pore_table_gen_api_fixed.C b/src/usr/hwpf/hwp/build_winkle_images/p8_slw_build/p8_pore_table_gen_api_fixed.C new file mode 100644 index 000000000..52ce97be3 --- /dev/null +++ b/src/usr/hwpf/hwp/build_winkle_images/p8_slw_build/p8_pore_table_gen_api_fixed.C @@ -0,0 +1,747 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/hwpf/hwp/build_winkle_images/p8_slw_build/p8_pore_table_gen_api_fixed.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: p8_pore_table_gen_api_fixed.C,v 1.6 2013/03/08 18:18:21 cmolsen Exp $ +// +/*------------------------------------------------------------------------------*/ +/* *! (C) Copyright International Business Machines Corp. 2012 */ +/* *! All Rights Reserved -- Property of IBM */ +/* *! *** IBM Confidential *** */ +/*------------------------------------------------------------------------------*/ +/* *! TITLE : p8_pore_table_gen_api_fixed.C */ +/* *! DESCRIPTION : PORE SLW table generaion APIs */ +/* *! OWNER NAME : Michael Olsen Email: cmolsen@us.ibm.com */ +/* *! USAGE : To build for PHYP command-line - */ +// buildecmdprcd_cmo -D "p8_pore_table_gen_api_fixed.C" -d "p8_pore_table_static_data.c,sbe_xip_image.c,pore_inline_assembler.c" -u "SLW_COMMAND_LINE_RAM" p8_pore_table_gen_api_fixed_main.C +// Other usages: +// +/* *! COMMENTS : - Start file: p7p_pore_api.c */ +// - The DYNAMIC_RAM_TABLE_PPD was dropped in v1.12 of this +// code. See v1.12 for explanation and code implementation. +// +/*------------------------------------------------------------------------------*/ + +#define __P8_PORE_TABLE_GEN_API_C +#include +#include +#include +#include + +/* +// io_image - pointer to SLW image +// i_modeBuild - 0: HB/IPL mode, 1: PHYP/Rebuild mode, 2: SRAM mode. +// i_regName - unswizzled enum SPR value (NOT a name) +// i_regData - data to write +// i_coreIndex - core ID +// i_threadIndex - thread to operate on, API changes thread num to 0 for shared +// SPRs, except for HRMOR which is always done on thread 3 to be +// the last SPR +*/ +uint32_t p8_pore_gen_cpureg_fixed( void *io_image, + uint8_t i_modeBuild, + uint32_t i_regName, + uint64_t i_regData, + uint32_t i_coreId, // [0:15] + uint32_t i_threadId) +{ + uint32_t rc=0, rcLoc=0, iCount=0; + int i=0, iReg=-1; + uint64_t xipSlwRamSection; + void *hostSlwRamSection; + void *hostSlwSectionFixed; + uint64_t xipRamTableThis; + void *hostRamVector; + void *hostRamTableThis; + void *hostRamEntryThis, *hostRamEntryNext; + uint8_t bNewTable=0, bFound=0; + uint8_t bEntryEnd=1, headerType=0; + SbeXipSection xipSection; + SbeXipItem xipTocItem; + RamTableEntry ramEntryThis, *ramEntryNext; + uint32_t sprSwiz=0; + + // ------------------------------------------------------------------------- + // Validate Ramming parameters. + // + // ...check mode build + if (i_modeBuild>P8_SLW_MODEBUILD_MAX_VALUE) { + MY_ERR("modeBuild=%i invalid. Valid range is [0;%i].", + i_modeBuild,P8_SLW_MODEBUILD_MAX_VALUE); + rcLoc = 1; + } + // ...check register value + bFound = 0; + for (i=0;i=SLW_MAX_CORES) { + MY_ERR("Core ID = %i is not within valid range of [0;%i]\n",i_coreId,SLW_MAX_CORES-1); + rcLoc = 1; + } + // ...check thread ID + if (i_threadId>=SLW_CORE_THREADS) { + MY_ERR("Thread ID = %i is not within valid range of [0;%i]\n",i_threadId,SLW_CORE_THREADS-1); + rcLoc = 1; + } + if (rcLoc) + return IMGBUILD_ERR_RAM_INVALID_PARM; + rcLoc = 0; + + // ------------------------------------------------------------------------- + // Get pointer to SLW section where Ram table resides + // NB! Only needed for modeBuild==2 ! + // + if (i_modeBuild==P8_SLW_MODEBUILD_IPL || + i_modeBuild==P8_SLW_MODEBUILD_REBUILD) { // Fixed image. + // CMO-20130114: Remove this asap. Only for fixed img transition. - Begin + // hostSlwSectionFixed isn't needed for modeBuild=0,1 ! + hostSlwSectionFixed = (void*)( (uintptr_t)io_image + + FIXED_SLW_IMAGE_SIZE - + FIXED_FFDC_SECTION_SIZE - + FIXED_SLW_SECTION_SIZE ); + // We may want to continue calling this because it would be practical to + // crosscheck the section size. Though, the offset is NOT reliable ! + rc = sbe_xip_get_section( io_image, SBE_XIP_SECTION_SLW, &xipSection); + if (rc) { + MY_ERR("Probably invalid section name for SBE_XIP_SECTION_SLW.\n"); + return IMGBUILD_ERR_GET_SECTION; + } + hostSlwRamSection = (void*)((uintptr_t)io_image + xipSection.iv_offset); + if (hostSlwSectionFixed!=hostSlwRamSection) { + MY_DBG("hostSlwSectionFixed != hostSlwRamSection(from image).\n"); + } + else { + MY_DBG("hostSlwSectionFixed == hostSlwRamSection(from image).\n"); + } + hostSlwRamSection = hostSlwSectionFixed; + // CMO-20130114: Remove this asap. Only for fixed img transition. - End + } + else { // SRAM non-fixed image. + rc = sbe_xip_get_section( io_image, SBE_XIP_SECTION_SLW, &xipSection); + if (rc) { + MY_ERR("Probably invalid section name for SBE_XIP_SECTION_SLW.\n"); + return IMGBUILD_ERR_GET_SECTION; + } + hostSlwRamSection = (void*)((uintptr_t)io_image + xipSection.iv_offset); + sbe_xip_host2pore( io_image, hostSlwRamSection, &xipSlwRamSection); + } + + // ------------------------------------------------------------------------- + // Cross check SPR register and table defines + // + if (SLW_SPR_REGS_SIZE!=(SLW_MAX_CPUREGS_CORE+SLW_MAX_CPUREGS_THREADS)) { + MY_ERR("Defines in *.H header file not in sync.\n"); + return IMGBUILD_ERR_RAM_HDRS_NOT_SYNCED; + } + if (xipSection.iv_size!=FIXED_SLW_SECTION_SIZE) { + MY_ERR("Fixed SLW table size in *.H header file differs from SLW section size in image.\n"); + MY_ERR("Check code or image version.\n"); + return IMGBUILD_ERR_RAM_HDRS_NOT_SYNCED; + } + + // ------------------------------------------------------------------------- + // Summarize parameters and checking results. + // + MY_INF("Input parameter checks - OK\n"); + MY_INF("\tMode build= %i\n",i_modeBuild); + MY_INF("\tRegister = (%s,%i)\n",SLW_SPR_REGS[iReg].name,SLW_SPR_REGS[iReg].value); + MY_INF("\tCore ID = %i\n",i_coreId); + MY_INF("\tThread ID = %i\n",i_threadId); + MY_INF("Image validation and size checks - OK\n"); + MY_INF("\tSLW section size= %i\n",xipSection.iv_size); + + // ------------------------------------------------------------------------- + // Locate RAM vector and locate RAM table associated with "This" core ID. + // + if (i_modeBuild==P8_SLW_MODEBUILD_IPL || + i_modeBuild==P8_SLW_MODEBUILD_REBUILD) { // Fixed image. + hostRamTableThis = (void*)( (uintptr_t)io_image + + FIXED_SLW_IMAGE_SIZE - + FIXED_FFDC_SECTION_SIZE - + FIXED_SLW_SECTION_SIZE + + SLW_RAM_TABLE_SPACE_PER_CORE*i_coreId ); + if (*(uintptr_t*)hostRamTableThis) { // Table content NOT empty. + bNewTable = 0; // So, NOT new table. + } + else { // Table content empty. + bNewTable = 1; // So, new table. + } + } + else { // SRAM non-fixed image. + rc = sbe_xip_find( io_image, SLW_HOST_REG_VECTOR_TOC_NAME, &xipTocItem); + if (rc) { + MY_ERR("Probably invalid key word for SLW_HOST_REG_VECTOR_TOC_NAME.\n"); + return IMGBUILD_ERR_KEYWORD_NOT_FOUND; + } + sbe_xip_pore2host( io_image, xipTocItem.iv_address, &hostRamVector); + xipRamTableThis = myRev64(*((uint64_t*)hostRamVector + i_coreId)); + if (xipRamTableThis) { + sbe_xip_pore2host( io_image, xipRamTableThis, &hostRamTableThis); + bNewTable = 0; + } + else { + hostRamTableThis = (void*)( (uintptr_t)hostSlwRamSection + + SLW_RAM_TABLE_SPACE_PER_CORE*i_coreId ); + bNewTable = 1; + } + } + + // ------------------------------------------------------------------------- + // Determine insertion point, hostRamEntryThis, of new RAM entry + // + if (bNewTable) { + // Append to beginning of agreed upon static Ram table position for this coreId. + hostRamEntryThis = hostRamTableThis; + if (i_modeBuild==P8_SLW_MODEBUILD_SRAM) { + // Update RAM vector (since it is currently NULL) + *((uint64_t*)hostRamVector + i_coreId) = + myRev64( xipSlwRamSection + + SLW_RAM_TABLE_SPACE_PER_CORE*i_coreId ); + } + bEntryEnd = 1; + } + else { + // Insert at end of existing Ram table for this coreId. + hostRamEntryNext = hostRamTableThis; + ramEntryNext = (RamTableEntry*)hostRamEntryNext; + iCount = 1; + while ((myRev32(ramEntryNext->header) & RAM_HEADER_END_MASK_C)==0) { + if (iCount>=SLW_MAX_CPUREGS_OPS) { + MY_ERR("Bad table! Header end bit not found and RAM table full (=%i entries).\n",SLW_MAX_CPUREGS_OPS); + return IMGBUILD_ERR_RAM_TABLE_END_NOT_FOUND; + } + hostRamEntryNext = (void*)((uint8_t*)hostRamEntryNext + XIPSIZE_RAM_ENTRY); + ramEntryNext = (RamTableEntry*)hostRamEntryNext; + iCount++; + } + if (iCountheader) & RAM_HEADER_END_MASK_C)) { + ramEntryNext->header = ramEntryNext->header & myRev32(~RAM_HEADER_END_MASK_C); + } + else { + MY_ERR("We should never get here. Check code. Dumping data:\n"); + MY_ERR("myRev32(ramEntryNext->header) = 0x%08x\n",myRev32(ramEntryNext->header)); + MY_ERR("RAM_HEADER_END_MASK_C = 0x%08x\n",RAM_HEADER_END_MASK_C); + return IMGBUILD_ERR_RAM_CODE; + } + } + else { + MY_ERR("RAM table is full. Max %i entries allowed.\n",SLW_MAX_CPUREGS_OPS); + return IMGBUILD_ERR_RAM_TABLE_FULL; + } + // ...this is the spot for the new entry + hostRamEntryThis = (void*)((uint8_t*)hostRamEntryNext + XIPSIZE_RAM_ENTRY); + bEntryEnd = 1; + } + + + // ------------------------------------------------------------------------- + // Create, or modify, the RAM entry. + // + if (i_regName==P8_MSR_MSR) { + // ...do the MSR header + headerType = 0x1; // MTMSRD header. + ramEntryThis.header = ( ((uint32_t)bEntryEnd) << RAM_HEADER_END_START_C & RAM_HEADER_END_MASK_C ) | + ( ((uint32_t)headerType) << RAM_HEADER_TYPE_START_C & RAM_HEADER_TYPE_MASK_C ); + // ...do the MSR instr + ramEntryThis.instr = RAM_MTMSRD_INSTR_TEMPL_C; + } + else { + // ...do the SPR header + headerType = 0x0; // MTSPR header. + ramEntryThis.header = ( ((uint32_t)bEntryEnd) << RAM_HEADER_END_START_C & RAM_HEADER_END_MASK_C ) | + ( ((uint32_t)headerType) << RAM_HEADER_TYPE_START_C & RAM_HEADER_TYPE_MASK_C ) | + ( i_regName << RAM_HEADER_SPRN_START_C & RAM_HEADER_SPRN_MASK_C ) | + ( i_threadId << RAM_HEADER_THREAD_START_C & RAM_HEADER_THREAD_MASK_C ); + // ...do the SPR instr + sprSwiz = i_regName>>5 | (i_regName & 0x0000001f)<<5; + if (sprSwiz!=SLW_SPR_REGS[iReg].swizzled) { + MY_ERR("Inconsistent swizzle rules implemented. Check code. Dumping data.\n"); + MY_ERR("\tsprSwiz (on-the-fly-calc)=%i\n",sprSwiz); + MY_ERR("\tSLW_SPR_REGS[%i].swizzled=%i\n",iReg,SLW_SPR_REGS[iReg].swizzled); + return IMGBUILD_ERR_RAM_CODE; + } + ramEntryThis.instr = RAM_MTSPR_INSTR_TEMPL_C | ( ( sprSwiz<header)!=0) { + MY_ERR("WARNING : Table entry location should be empty for a new table. Check code and image. Dumping data:\n"); + MY_ERR("\theader = 0x%08x\n",myRev32(ramEntryNext->header)); + MY_ERR("\tinstr = 0x%08x\n",myRev32(ramEntryNext->instr)); + MY_ERR("\tdata = 0x%016llx\n",myRev64(ramEntryNext->data)); + rc = IMGBUILD_WARN_RAM_TABLE_CONTAMINATION; + } + } + ramEntryNext->header = myRev32(ramEntryThis.header); + ramEntryNext->instr = myRev32(ramEntryThis.instr); + ramEntryNext->data = myRev64(ramEntryThis.data); + + return rc; +} + + +/* +// io_image - Pointer to SLW image. +// i_modeBuild - 0: HB/IPL mode, 1: PHYP/Rebuild mode, 2: SRAM mode. +// i_scomAddr - Scom address. +// i_coreId - The core ID [0:15]. +// i_scomData - Data to write to scom register. +// i_operation - What to do with the scom addr and data. +// i_section - 0: General Scoms, 1: L2 cache, 2: L3 cache. +*/ +uint32_t p8_pore_gen_scom_fixed( void *io_image, + uint8_t i_modeBuild, + uint32_t i_scomAddr, + uint32_t i_coreId, // [0:15] + uint64_t i_scomData, + uint32_t i_operation, // [0:5] + uint32_t i_section) // [0,1,2] +{ + uint32_t rc=0, rcLoc=0, iEntry=0; + uint32_t chipletId=0; + uint32_t operation=0; + uint32_t entriesCount=0, entriesMatch=0, entriesNOP=0; + void *hostSlwSection; + void *hostSlwSectionFixed; + uint64_t xipScomTableThis; + void *hostScomVector, *hostScomTableThis; + void *hostScomEntryNext; // running entry pointer + void *hostScomEntryMatch=NULL; // pointer to entry that matches scomAddr + void *hostScomEntryRET=NULL; // pointer to first return instr after table + void *hostScomEntryNOP=NULL; // pointer to first nop IIS + uint8_t bufIIS[XIPSIZE_SCOM_ENTRY], bufNOP[4], bufRET[4]; + SbeXipSection xipSection; + SbeXipItem xipTocItem; + PoreInlineContext ctx; + + // ------------------------------------------------------------------------- + // Validate Scom parameters. + // + // ...check if valid Scom register (is there anything we can do here to check?) + // Skipping check. We blindly trust caller. + // + // ...check mode build + if (i_modeBuild>P8_SLW_MODEBUILD_MAX_VALUE) { + MY_ERR("modeBuild=%i invalid. Valid range is [0;%i].", + i_modeBuild,P8_SLW_MODEBUILD_MAX_VALUE); + rcLoc = 1; + } + // ...check Scom operation + if (i_operationP8_PORE_SCOM_LAST_OP) { + MY_ERR("Scom operation = %i is not within valid range of [%d;%d]\n", + i_operation, P8_PORE_SCOM_FIRST_OP, P8_PORE_SCOM_LAST_OP); + rcLoc = 1; + } + // ...check that core ID corresponds to valid chiplet ID + chipletId = i_coreId + P8_CID_EX_LOW; + if (chipletIdP8_CID_EX_HIGH) { + MY_ERR("Chiplet ID = 0x%02x is not within valid range of [0x%02x;0x%02x]\n", + chipletId, P8_CID_EX_LOW, P8_CID_EX_HIGH); + rcLoc = 1; + } + if (rcLoc) + return IMGBUILD_ERR_SCOM_INVALID_PARM; + rcLoc = 0; + + // ------------------------------------------------------------------------- + // Get pointer to SLW section where Scom table resides + // NB! Only needed for modeBuild==2 ! + // + if (i_modeBuild==P8_SLW_MODEBUILD_IPL || + i_modeBuild==P8_SLW_MODEBUILD_REBUILD) { // Fixed image. + // CMO-20130114: Remove this asap. Only for fixed img transition. - Begin + // hostSlwSectionFixed isn't needed for modeBuild=0,1 ! + hostSlwSectionFixed = (void*)( (uintptr_t)io_image + + FIXED_SLW_IMAGE_SIZE - + FIXED_FFDC_SECTION_SIZE - + FIXED_SLW_SECTION_SIZE ); + // We may want to continue calling this because it would be practical to + // crosscheck the section size. Though, the offset is NOT reliable ! + rc = sbe_xip_get_section( io_image, SBE_XIP_SECTION_SLW, &xipSection); + if (rc) { + MY_ERR("Probably invalid section name for SBE_XIP_SECTION_SLW.\n"); + return IMGBUILD_ERR_GET_SECTION; + } + hostSlwSection = (void*)((uintptr_t)io_image + xipSection.iv_offset); + if (hostSlwSectionFixed!=hostSlwSection) { + MY_DBG("hostSlwSectionFixed != hostSlwSection(from image).\n"); + } + else { + MY_DBG("hostSlwSectionFixed == hostSlwSection(from image).\n"); + } + hostSlwSection = hostSlwSectionFixed; + // CMO-20130114: Remove this asap. Only for fixed img transition. - End + } + else { // SRAM non-fixed image. + rc = sbe_xip_get_section( io_image, SBE_XIP_SECTION_SLW, &xipSection); + if (rc) { + MY_ERR("Probably invalid section name for SBE_XIP_SECTION_SLW.\n"); + return IMGBUILD_ERR_GET_SECTION; + } + hostSlwSection = (void*)((uintptr_t)io_image + xipSection.iv_offset); + } + + // ------------------------------------------------------------------------- + // Check .slw section size and cross-check w/header define. + // + if (xipSection.iv_size!=FIXED_SLW_SECTION_SIZE) { + MY_ERR("SLW table size in *.H header file (=%i) differs from SLW section size in image (=%i).\n",FIXED_SLW_SECTION_SIZE,xipSection.iv_size); + MY_ERR("Check code or image version.\n"); + return IMGBUILD_ERR_SCOM_HDRS_NOT_SYNCD; + } + + // ------------------------------------------------------------------------- + // Summarize parameters and checking results. + // + MY_INF("Input parameter checks - OK\n"); + MY_INF("\tRegister = 0x%08x\n",i_scomAddr); + MY_INF("\tOperation = %i\n",i_operation); + MY_INF("\tSection = %i\n",i_section); + MY_INF("\tCore ID = %i\n",i_coreId); + MY_INF("Image validation and size checks - OK\n"); + MY_INF("\tSLW section size= %i\n",xipSection.iv_size); + + // ------------------------------------------------------------------------- + // Locate Scom vector according to i_section and then locate Scom table + // associated with "This" core ID. + // + if (i_modeBuild==P8_SLW_MODEBUILD_IPL || + i_modeBuild==P8_SLW_MODEBUILD_REBUILD) { // Fixed image. + switch (i_section) { + case P8_SCOM_SECTION_NC: + hostScomTableThis = (void*)( (uintptr_t)hostSlwSection + + SLW_RAM_TABLE_SIZE + + SLW_SCOM_TABLE_SPACE_PER_CORE_NC*i_coreId ); + break; + case P8_SCOM_SECTION_L2: + hostScomTableThis = (void*)( (uintptr_t)hostSlwSection + + SLW_RAM_TABLE_SIZE + + SLW_SCOM_TABLE_SIZE_NC + + SLW_SCOM_TABLE_SPACE_PER_CORE_L2*i_coreId ); + break; + case P8_SCOM_SECTION_L3: + hostScomTableThis = (void*)( (uintptr_t)hostSlwSection + + SLW_RAM_TABLE_SIZE + + SLW_SCOM_TABLE_SIZE_NC + + SLW_SCOM_TABLE_SIZE_L2 + + SLW_SCOM_TABLE_SPACE_PER_CORE_L3*i_coreId ); + break; + default: + MY_ERR("Invalid value for i_section (=%i).\n",i_section); + MY_ERR("Valid values for i_section = [%i,%i,%i].\n", + P8_SCOM_SECTION_NC,P8_SCOM_SECTION_L2,P8_SCOM_SECTION_L3); + return IMGBUILD_ERR_SCOM_INVALID_SUBSECTION; + break; + } + } + else { // SRAM non-fixed image. + switch (i_section) { + case P8_SCOM_SECTION_NC: + rc = sbe_xip_find( io_image, SLW_HOST_SCOM_NC_VECTOR_TOC_NAME, &xipTocItem); + if (rc) { + MY_ERR("Probably invalid key word for SLW_HOST_SCOM_NC_VECTOR_TOC_NAME.\n"); + return IMGBUILD_ERR_KEYWORD_NOT_FOUND; + } + break; + case P8_SCOM_SECTION_L2: + rc = sbe_xip_find( io_image, SLW_HOST_SCOM_L2_VECTOR_TOC_NAME, &xipTocItem); + if (rc) { + MY_ERR("Probably invalid key word for SLW_HOST_SCOM_L2_VECTOR_TOC_NAME.\n"); + return IMGBUILD_ERR_KEYWORD_NOT_FOUND; + } + break; + case P8_SCOM_SECTION_L3: + rc = sbe_xip_find( io_image, SLW_HOST_SCOM_L3_VECTOR_TOC_NAME, &xipTocItem); + if (rc) { + MY_ERR("Probably invalid key word for SLW_HOST_SCOM_L3_VECTOR_TOC_NAME.\n"); + return IMGBUILD_ERR_KEYWORD_NOT_FOUND; + } + break; + default: + MY_ERR("Invalid value for i_section (=%i).\n",i_section); + MY_ERR("Valid values for i_section = [%i,%i,%i].\n", + P8_SCOM_SECTION_NC,P8_SCOM_SECTION_L2,P8_SCOM_SECTION_L3); + return IMGBUILD_ERR_SCOM_INVALID_SUBSECTION; + } + MY_INF("xipTocItem.iv_address = 0x%016llx\n",xipTocItem.iv_address); + sbe_xip_pore2host( io_image, xipTocItem.iv_address, &hostScomVector); + MY_INF("hostScomVector = 0x%016llx\n",(uint64_t)hostScomVector); + xipScomTableThis = myRev64(*((uint64_t*)hostScomVector + i_coreId)); + MY_INF("xipScomTableThis = 0x%016llx\n",xipScomTableThis); + if (xipScomTableThis) { + sbe_xip_pore2host( io_image, xipScomTableThis, &hostScomTableThis); + } + else { // Should never be here. + MY_ERR("Code or image bug. Scom vector table entries should never be null.\n"); + return IMGBUILD_ERR_CHECK_CODE; + } + } + + // + // Determine where to place/do Scom action and if entry already exists. + // Insertion rules: + // - If entry doesn't exist, insert at first NOP. (Note that if you don't do + // this, then the table might potentially overflow since the max table size + // doesn't include NOP entries.) + // - If no NOP found, insert at first RET. + // + + // First, create search strings for addr, nop and ret. + // Note, the following IIS will also be used in case of + // - i_operation==append + // - i_operation==replace + pore_inline_context_create( &ctx, (void*)bufIIS, XIPSIZE_SCOM_ENTRY, 0, 0); + pore_LS( &ctx, P1, chipletId); + pore_STI( &ctx, i_scomAddr, P1, i_scomData); + if (ctx.error > 0) { + MY_ERR("pore_LS or _STI generated rc = %d", ctx.error); + return IMGBUILD_ERR_PORE_INLINE_ASM; + } + pore_inline_context_create( &ctx, (void*)bufRET, 4, 0, 0); + pore_RET( &ctx); + if (ctx.error > 0) { + MY_ERR("pore_RET generated rc = %d", ctx.error); + return IMGBUILD_ERR_PORE_INLINE_ASM; + } + pore_inline_context_create( &ctx, (void*)bufNOP, 4, 0, 0); + pore_NOP( &ctx); + if (ctx.error > 0) { + MY_ERR("pore_NOP generated rc = %d", ctx.error); + return IMGBUILD_ERR_PORE_INLINE_ASM; + } + + // Second, search for addr and nop in relevant coreId table until first RET. + // Note: + // - We go through ALL entries until first RET instr. We MUST find a RET instr, + // though we don't check for overrun until later. (Should be improved.) + // - Count number of entries and check for overrun, though we'll continue + // searching until we find an RET. (Should be improved.) + // - The STI(+SCOM_addr) opcode is in the 2nd word of the Scom entry. + // - For an append operation, if a NOP is found (before a RET obviously), the + // SCOM is replacing that NNNN sequence. + hostScomEntryNext = hostScomTableThis; + MY_DBG("hostScomEntryNext (addr): 0x%016llx\n ",(uint64_t)hostScomEntryNext); + while (*(uint32_t*)hostScomEntryNext!=*(uint32_t*)bufRET) { + entriesCount++; + MY_DBG("Number of SCOM entries: %i\n ",entriesCount); + if (*((uint32_t*)bufIIS+1)==*((uint32_t*)hostScomEntryNext+1) && entriesMatch==0) {// +1 skips 1st word in Scom entry (which loads the PC in an LS operation.) + hostScomEntryMatch = hostScomEntryNext; + entriesMatch++; + } + if (*(uint32_t*)hostScomEntryNext==*(uint32_t*)bufNOP && entriesNOP==0) { + hostScomEntryNOP = hostScomEntryNext; + entriesNOP++; + } + hostScomEntryNext = (void*)((uintptr_t)hostScomEntryNext + XIPSIZE_SCOM_ENTRY); + } + hostScomEntryRET = hostScomEntryNext; // The last EntryNext is always the first RET. + + switch (i_section) { + case P8_SCOM_SECTION_NC: + if (entriesCount>=SLW_MAX_SCOMS_NC) { + MY_ERR("SCOM table NC is full. Max %i entries allowed.\n",SLW_MAX_SCOMS_NC); + return IMGBUILD_ERR_CHECK_CODE; + } + break; + case P8_SCOM_SECTION_L2: + if (entriesCount>=SLW_MAX_SCOMS_L2) { + MY_ERR("SCOM table L2 is full. Max %i entries allowed.\n",SLW_MAX_SCOMS_L2); + return IMGBUILD_ERR_CHECK_CODE; + } + break; + case P8_SCOM_SECTION_L3: + if (entriesCount>=SLW_MAX_SCOMS_L3) { + MY_ERR("SCOM table L3 is full. Max %i entries allowed.\n",SLW_MAX_SCOMS_L3); + return IMGBUILD_ERR_CHECK_CODE; + } + break; + default: + MY_ERR("Invalid value for i_section (=%i).\n",i_section); + MY_ERR("Valid values for i_section = [%i,%i,%i].\n", + P8_SCOM_SECTION_NC,P8_SCOM_SECTION_L2,P8_SCOM_SECTION_L3); + return IMGBUILD_ERR_SCOM_INVALID_SUBSECTION; + } + + // + // Further qualify (translate) operation and IIS. + // + if (i_operation==P8_PORE_SCOM_APPEND) { + operation = i_operation; + } + else if (i_operation==P8_PORE_SCOM_REPLACE) { + if (hostScomEntryMatch) + // ... do a replace + operation = i_operation; + else + // ... do an append + operation = P8_PORE_SCOM_APPEND; + } + else if (i_operation==P8_PORE_SCOM_NOOP) { + // ...overwrite earlier bufIIS from the search step + pore_inline_context_create( &ctx, (void*)bufIIS, XIPSIZE_SCOM_ENTRY, 0, 0); + pore_NOP( &ctx); + pore_NOP( &ctx); + pore_NOP( &ctx); + pore_NOP( &ctx); + if (ctx.error > 0) { + MY_ERR("*** _NOP generated rc = %d", ctx.error); + return IMGBUILD_ERR_PORE_INLINE_ASM; + } + operation = i_operation; + } + else if (i_operation==P8_PORE_SCOM_AND || + i_operation==P8_PORE_SCOM_OR) { + operation = i_operation; + } + else if (i_operation==P8_PORE_SCOM_RESET) { + // ... create RNNN instruction sequence. + pore_inline_context_create( &ctx, (void*)bufIIS, XIPSIZE_SCOM_ENTRY, 0, 0); + pore_RET( &ctx); + pore_NOP( &ctx); + pore_NOP( &ctx); + pore_NOP( &ctx); + if (ctx.error > 0) { + MY_ERR("***_RET or _NOP generated rc = %d", ctx.error); + return IMGBUILD_ERR_PORE_INLINE_ASM; + } + operation = i_operation; + } + else { + MY_ERR("Scom operation = %i is not within valid range of [%d;%d]\n", + i_operation, P8_PORE_SCOM_FIRST_OP, P8_PORE_SCOM_LAST_OP); + return IMGBUILD_ERR_SCOM_INVALID_PARM; + } + + // ------------------------------------------------------------------------- + // Assuming pre-allocated Scom table (after pre-allocated Ram table): + // - Table is pre-filled with RNNN ISS. + // - Each core Id has dedicated space, uniformly distributed by SLW_MAX_SCOMS_NC* + // XIPSIZE_SCOM_ENTRY. + // - Remember to check for more than SLW_MAX_SCOMS_NC entries! + switch (operation) { + + case P8_PORE_SCOM_APPEND: // Append a Scom at first occurring NNNN or RNNN, + if (hostScomEntryNOP) { + // ... replace the NNNN + MY_INF("Append at NOP\n"); + memcpy(hostScomEntryNOP,(void*)bufIIS,XIPSIZE_SCOM_ENTRY); + } + else if (hostScomEntryRET) { + // ... replace the RNNN + MY_INF("Append at RET\n"); + memcpy(hostScomEntryRET,(void*)bufIIS,XIPSIZE_SCOM_ENTRY); + } + else { + // We should never be here. + MY_ERR("In case=_SCOM_APPEND: EntryRET=NULL is impossible. Check code.\n"); + return IMGBUILD_ERR_CHECK_CODE; + } + break; + case P8_PORE_SCOM_REPLACE: // Replace existing Scom with new data + if (hostScomEntryMatch) { + // ... do a vanilla replace + MY_INF("Replace existing Scom\n"); + memcpy(hostScomEntryMatch,(void*)bufIIS,XIPSIZE_SCOM_ENTRY); + } + else { + // We should never be here. + MY_ERR("In case=_SCOM_REPLACE: EntryMatch=NULL is impossible. Check code.\n"); + return IMGBUILD_ERR_CHECK_CODE; + } + break; + case P8_PORE_SCOM_NOOP: + if (hostScomEntryMatch) { + // ... do a vanilla replace + MY_INF("Replace existing Scom w/NOPs\n"); + memcpy(hostScomEntryMatch,(void*)bufIIS,XIPSIZE_SCOM_ENTRY); + } + else { + // do nothing, and assume everything is fine, since we did no damage. + } + break; + case P8_PORE_SCOM_OR: // Overlay Scom data onto existing data by bitwise OR + if (hostScomEntryMatch) { + // ... do an OR on the data (which is the 2nd DWord in the entry) + MY_INF("Overlay existing Scom - OR case\n"); + *((uint64_t*)hostScomEntryMatch+1) = + *((uint64_t*)hostScomEntryMatch+1) | myRev64(i_scomData); + } + else { + MY_ERR("No Scom entry found to do OR operation with.\n"); + return IMGBUILD_ERR_SCOM_ENTRY_NOT_FOUND; + } + break; + case P8_PORE_SCOM_AND: // Overlay Scom data onto existing data by bitwise AND + if (hostScomEntryMatch) { + // ... do an AND on the data (which is the 2nd DWord in the entry) + MY_INF("Overlay existing Scom - AND case\n"); + *((uint64_t*)hostScomEntryMatch+1) = + *((uint64_t*)hostScomEntryMatch+1) & myRev64(i_scomData); + } + else { + MY_ERR("No Scom entry found to do AND operation with.\n"); + return IMGBUILD_ERR_SCOM_ENTRY_NOT_FOUND; + } + break; + case P8_PORE_SCOM_RESET: // Reset (delete) table. Refill w/RNNN ISS. + MY_INF("Reset table\n"); + hostScomEntryNext = hostScomTableThis; + for ( iEntry=0; iEntry