diff options
Diffstat (limited to 'src/ssx/pgp/pgp_centaur.c')
-rw-r--r-- | src/ssx/pgp/pgp_centaur.c | 644 |
1 files changed, 0 insertions, 644 deletions
diff --git a/src/ssx/pgp/pgp_centaur.c b/src/ssx/pgp/pgp_centaur.c deleted file mode 100644 index 85a0dd3..0000000 --- a/src/ssx/pgp/pgp_centaur.c +++ /dev/null @@ -1,644 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/ssx/pgp/pgp_centaur.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -// $Id: pgp_centaur.c,v 1.6 2015/01/27 17:56:26 daviddu Exp $ -// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_centaur.c,v $ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2013 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pgp_centaur.c -/// \brief Support for Centaur access and configuration from OCC. -/// -/// Generic PBA generated PowerBus Address in pictures and words: -/// -/// \code -/// -/// 1 2 3 4 5 6 -/// 0123456789012345678901234567890123456789012345678901234567890123 -/// | | | | | | | | | | | | | | | -/// -/// ..............B-------BX------------XO-----OA------------------A -/// -/// .: Unused -/// B: Direct from PBA BAR, bits 14:22 -/// X: If PBA BAR MASK 23:36 == 0, then PBA BAR 23:36 -/// Else Extended Address 0:13 -/// O: If PBA BAR MASK 37:43 == 0, then PBA BAR 37:43 -/// Else OCI Address 5:11 -/// A: OCI Address 12:31 -/// -/// \endcode -/// -/// The OCI address always selects the low-order 20 bits of the PowerBus -/// address, i.e., the window size is always a multiple of 1MB. The PBA BAR -/// mask allows up to a 128MB window into main memory without using the -/// extended address. The extended address allows OCC to address up to 2^41 -/// bytes by manipulating the extended address, assuming PHYP sets up the mask -/// correctly. -/// -/// -/// Centaur in-band SCOM, sensor cache and SYNC addressing in pictures and words: -/// -/// \code -/// -/// 1 2 3 4 5 6 -/// 0123456789012345678901234567890123456789012345678901234567890123 -/// | | | | | | | | | | | | | | | -/// -/// ..............B-------BX------------XO-----OA------------------A - See Above -/// ..............M-----------M10S------------------------------S000 - SCOM -/// ..............M-----------M1100000000000000000000000000000000000 - Sensor cache -/// ..............M-----------M1110000000000000000000000000000000000 - Sync -/// -/// .: Unused -/// M: The base address of the Centaur, taken from the MCS MCFGPR. -/// O: 1 Signifies that this access comes from the OCC. -/// S: The 32-bit SCOM address -/// 0: Zero -/// -/// \endcode -/// -/// In order to access the Centaur for in-band SCOM, the PBA BAR MASK must -/// extend at least from bit 29 down to bit 43, in order to allow the OCC to -/// generate these addresses. In practice the mask must allow all configured -/// Centaur to be accessed. This means that all Centaur in-band address bits -/// not controllable by OCC through the mask must be equal. -/// -/// Note that the SCOM address must be split between the extended address and -/// the OCI address. -/// -/// We assume (and verify) that MCMODE0(36) will always be set which means -/// that bit 27 is a flag indicating whether an access comes from FSP or -/// OCC. All OCC (GPE) accesses set this flag to 1. - -#include "ssx.h" -#include "gpe_scom.h" - -#if defined(VERIFICATION) || defined(LAB_VALIDATION) -#define PRINTD(...) printk(__VA_ARGS__) -#else -#define PRINTD(...) -#endif - -CentaurConfiguration G_centaurConfiguration -SECTION_ATTRIBUTE(".noncacheable_ro") = {.configRc = CENTAUR_NOT_CONFIGURED}; - -const uint16_t _pgp_mcs_offset[PGP_NMCS] = { - 0x0800, 0x0880, 0x0900, 0x0980, 0x0c00, 0x0c80, 0x0d00, 0x0d80 -}; - - -// All GpeScomParms structures are required to be noncacheable, so we have to -// allocate a static instance rather than using the stack. For simplicity the -// single-entry scomList_t required to collect the Centaur device IDs is -// allocated statically as well. - -static GpeScomParms S_parms SECTION_ATTRIBUTE(".noncacheable") = {0}; -static scomList_t S_scomList SECTION_ATTRIBUTE(".noncacheable") = {{{0}}}; - -int -_centaur_configuration_create(int i_bar, int i_slave, int i_setup) -{ - CentaurConfiguration config; - int i, designatedSync, diffInit; - int64_t rc; /* Must be copied to global struct. */ - mcfgpr_t mcfgpr; - mcifir_t mcifir; - mcsmode0_t mcsmode0; - pba_slvctln_t slvctl; - uint64_t diffMask, addrAccum, bar, mask, base; - PoreFlex request; - - // Start by clearing the local structure and setting the error flag. - memset(&config, 0, sizeof(config)); - config.configRc = CENTAUR_NOT_CONFIGURED; - - designatedSync = -1; - - do { - // Basic consistency checks - - if ((i_bar < 0) || (i_bar >= PBA_BARS) || - (i_slave < 0) || (i_slave >= PBA_SLAVES)) { - - rc = CENTAUR_INVALID_ARGUMENT; - break; - } - - - // Create the setups for the GPE procedures. The 'dataParms' are the - // setup for accessing the Centaur sensor cache. The 'scomParms' are - // the setup for accessing Centaur SCOMs. - - rc = gpe_pba_parms_create(&(config.dataParms), - PBA_SLAVE_PORE_GPE, - PBA_WRITE_TTYPE_CI_PR_W, - PBA_WRITE_TTYPE_DC, - PBA_READ_TTYPE_CL_RD_NC); - if (rc) { - rc = CENTAUR_DATA_SETUP_ERROR; - break; - } - - rc = gpe_pba_parms_create(&(config.scomParms), - PBA_SLAVE_PORE_GPE, - PBA_WRITE_TTYPE_CI_PR_W, - PBA_WRITE_TTYPE_DC, - PBA_READ_TTYPE_CI_PR_RD); - if (rc) { - rc = CENTAUR_SCOM_SETUP_ERROR; - break; - } - - - // Go into each MCS on the chip, and for all enabled MCS get a couple - // of SCOMs and check configuration items for correctness. If any of - // the Centaur are configured, exactly one of the MCS must be - // designated to receive the SYNC commands. - - // Note that the code uniformly treats SCOM failures of the MCFGPR - // registers as an unconfigured Centaur. This works both for Murano, - // which only defines the final 4 MCS, as well as for our VBU models - // where some of the "valid" MCS are not in the simulation models. - - for (i = 0; i < PGP_NCENTAUR; i++) { - - // SW273928: New function added for FW820, when centaur has channel - // checkstop, we consider centaur is not usable so treat it as - // deconfigured. Note that the current implementation assumes when - // centaur is dead, its mcs is also dead, which is wrong. However, - // it only concerns when MCS happens to be the SYNC master because - // the gpe procedure only tries to talk to centaurs regardless what - // MCS status it knows about. In this particular case, - // the procedure will turn on SYNC on a different MCS with - // valid centaur. According to Eric Retter, it would be ok for - // HW to have more MCS turned on as SYNC master as long as FW - // only send SYNC command to one of them. - - rc = _getscom(MCS_ADDRESS(MCIFIR, i), &(mcifir.value), - SCOM_TIMEOUT); - if (rc) { - rc = 0; - config.baseAddress[i] = 0; - continue; - } - - if (mcifir.fields.channel_fail_signal_active) continue; - - rc = _getscom(MCS_ADDRESS(MCFGPR, i), &(mcfgpr.value), - SCOM_TIMEOUT); - if (rc) { - rc = 0; - config.baseAddress[i] = 0; - continue; - } - - if (!mcfgpr.fields.mcfgprq_valid) continue; - - rc = _getscom(MCS_ADDRESS(MCSMODE0, i), &(mcsmode0.value), - SCOM_TIMEOUT); - if (rc) { - PRINTD("Unexpected rc = 0x%08x SCOMing MCSMODE0(%d)\n", - (uint32_t)rc, i); - rc = CENTAUR_MCSMODE0_SCOM_FAILURE; - break; - } - - - // We require that the MCFGRP_19_IS_HO_BIT be set in the mode - // register. We do not support the option of this bit not being - // set, and all of our procedures will set bit 19 of the PowerBus - // address to indicate that OCC is making the access. - - if (!mcsmode0.fields.mcfgrp_19_is_ho_bit) { - - PRINTD("MCSMODE0(%d).mcfgrp_19_is_ho_bit == 0\n", i); - rc = CENTAUR_MCSMODE0_19_FAILURE; - break; - } - - - // The 14-bit base-address is moved to begin at bit 14 in the - // 64-bit PowerBus address. The low-order bit of this address (bit - // 19 mentioned above which is bit 27 as an address bit) must be 0 - // - otherwise there is confusion over who's controlling this - // bit. - - config.baseAddress[i] = - ((uint64_t)(mcfgpr.fields.mcfgprq_base_address)) << - (64 - 14 - 14); - - if (config.baseAddress[i] & 0x0000001000000000ull) { - - PRINTD("Centaur base address %d has bit 27 set\n", i); - rc = CENTAUR_ADDRESS_27_FAILURE; - break; - } - - - // If this MCS is configured to be the designated SYNC unit, it - // must be the only one. - - if (mcsmode0.fields.enable_centaur_sync) { - - if (designatedSync > 0) { - - PRINTD("Both MCS %d and %d are designated " - "for Centaur Sync\n", - designatedSync, i); - rc = CENTAUR_MULTIPLE_DESIGNATED_SYNC; - break; - - } else { - - designatedSync = i; - } - } - - - // Add the Centaur to the configuration - - config.config |= (CHIP_CONFIG_MCS(i) | CHIP_CONFIG_CENTAUR(i)); - } - - if (rc) break; - - - // If Centaur are configured, make sure at least one of the MCS will - // handle the SYNC. If so, convert its base address into an address - // for issuing SYNC commands by setting bits 27 (OCC) 28 and 29 - // (Sync), then insert this address into the extended address field of - // a PBA slave control register image. gsc_scom_centaur() then merges - // this extended address into the PBA slave control register (which - // has been set up for Centaur SCOM) to do the SYNC. - - // In the override mode (i_setup > 1) we tag the first valid MCS - // to recieve the sync if the firmware has not set it up correctly. - - if (config.config) { - - if (designatedSync < 0) { - - if (i_setup <= 1) { - - PRINTD("No MCS is designated for Centaur SYNC\n"); - rc = CENTAUR_NO_DESIGNATED_SYNC; - break; - - } else { - - designatedSync = - cntlz32(left_justify_mcs_config(config.config)); - - rc = _getscom(MCS_ADDRESS(MCSMODE0, designatedSync), - &(mcsmode0.value), - SCOM_TIMEOUT); - if (rc) { - PRINTD("Unexpected rc = 0x%08x SCOMing MCSMODE0(%d)\n", - (uint32_t)rc, designatedSync); - rc = CENTAUR_MCSMODE0_SCOM_FAILURE; - break; - } - - mcsmode0.fields.enable_centaur_sync = 1; - - rc = _putscom(MCS_ADDRESS(MCSMODE0, designatedSync), - mcsmode0.value, - SCOM_TIMEOUT); - if (rc) { - PRINTD("Unexpected rc = 0x%08x SCOMing MCSMODE0(%d)\n", - (uint32_t)rc, designatedSync); - rc = CENTAUR_MCSMODE0_SCOM_FAILURE; - break; - } - } - } - - base = config.baseAddress[designatedSync] | 0x0000001c00000000ull; - - slvctl.value = 0; - slvctl.fields.extaddr = (base & 0x000001fff8000000ull) >> 27; - - config.syncSlaveControl = slvctl.value; - } - - - // At this point we have one or more enabled MCS and they pass the - // initial configuration sniff test. We can now implement the option - // to configure the PBA BAR and BAR MASK correctly to allow access to - // these Centaur. We do this by computing the minimum BAR mask that - // covers all of the Centaur base addresses. This is done by - // accumulating a difference mask of the base addresses and finding - // the first set bit in the mask. - // - // Note that we do the configuration here on demand, but always do the - // correctness checking as the next step. - - if (i_setup && (config.config != 0)) { - - diffInit = 0; - diffMask = 0; /* GCC happiness */ - addrAccum = 0; /* GCC happiness */ - - for (i = 0; i < PGP_NCENTAUR; i++) { - - if (config.baseAddress[i] != 0) { - - if (!diffInit) { - - diffInit = 1; - diffMask = 0; - addrAccum = config.baseAddress[i]; - - } else { - - diffMask |= - (config.baseAddress[i] ^ addrAccum); - addrAccum |= config.baseAddress[i]; - } - - if (0) { - - // Debug - - printk("i:%d baseAddress: 0x%016llx " - "diffMask: 0x%016llx, addrAccum: 0x%016llx\n", - i, config.baseAddress[i], diffMask, addrAccum); - } - } - } - - // The mask must cover all differences - and must also have at - // least bit 27 set. The mask register contains only the mask. The - // BAR is set to the accumulated address outside of the mask. The - // BAR also contains a scope field which defaults to 0 (Nodal - // Scope) for Centaur inband access. - - diffMask |= 0x0000001000000000ull; - mask = - ((1ull << (64 - cntlz64(diffMask))) - 1) & - PBA_BARMSKN_MASK_MASK; - - rc = _putscom(PBA_BARMSKN(i_bar), mask, SCOM_TIMEOUT); - if (rc) { - PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARMSKN(%d)\n", - (uint32_t)rc, i_bar); - rc = CENTAUR_BARMSKN_PUTSCOM_FAILURE; - break; - } - - rc = _putscom(PBA_BARN(i_bar), addrAccum & ~mask, SCOM_TIMEOUT); - if (rc) { - PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARN(%d)\n", - (uint32_t)rc, i_bar); - rc = CENTAUR_BARN_PUTSCOM_FAILURE; - break; - } - } - - - // Do an independent check that every Centaur base address - // can be generated by the combination of the current BAR and - // BAR Mask, along with the initial requirement that the mask must - // include at least bits 27:43. - - if (config.config != 0) { - - rc = _getscom(PBA_BARN(i_bar), &bar, SCOM_TIMEOUT); - if (rc) { - PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARN(%d)\n", - (uint32_t)rc, i_bar); - rc = CENTAUR_BARN_GETSCOM_FAILURE; - break; - } - - rc = _getscom(PBA_BARMSKN(i_bar), &mask, SCOM_TIMEOUT); - - if (rc) { - PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARMSKN(%d)\n", - (uint32_t)rc, i_bar); - rc = CENTAUR_BARMSKN_GETSCOM_FAILURE; - break; - } - - bar = bar & PBA_BARN_ADDR_MASK; - mask = mask & PBA_BARMSKN_MASK_MASK; - - if ((mask & 0x0000001ffff00000ull) != 0x0000001ffff00000ull) { - - PRINTD("PBA BAR mask (%d) does not cover bits 27:43\n", i_bar); - rc = CENTAUR_MASK_ERROR; - break; - } - - for (i = 0; i < PGP_NCENTAUR; i++) { - - if (config.baseAddress[i] != 0) { - - if ((config.baseAddress[i] & ~mask) != - (bar & ~mask)) { - - PRINTD("BAR/Mask (%d) error for MCS/Centaur %d\n" - " base = 0x%016llx\n" - " bar = 0x%016llx\n" - " mask = 0x%016llx\n", - - i_bar, i, config.baseAddress[i], bar, mask); - rc = CENTAUR_BAR_MASK_ERROR; - break; - } - } - } - - if (rc) break; - } - - - // At this point the structure is initialized well-enough that it can - // be used by gpe_scom_centaur(). We run gpe_scom_centaur() to collect - // the CFAM ids of the chips. Prior to this we copy our local copy - // into the global read-only data structure. (Note that GPE can DMA - // under the OCC TLB memory protection.) In order for - // gpe_scom_centaur() to run the global configuration must be valid - // (configRc == 0) - so we provisionally mark it valid (and will - // invalidate it later if errors occur here). - - // Note however that if no Centaur are present then we're already - // done. - - // It's assumed that this procedure is being run before threads have - // started, therefore we must poll for completion of the GPE program. - // Assuming no contention for GPE1 this procedure should take a few - // microseconds at most to complete. - - if (0) { - - // Debug for Simics - only enable MCS 5 - - config.baseAddress[0] = - config.baseAddress[1] = - config.baseAddress[2] = - config.baseAddress[3] = - config.baseAddress[4] = - config.baseAddress[6] = - config.baseAddress[7] = 0; - } - - - config.configRc = 0; - memcpy_real(&G_centaurConfiguration, &config, sizeof(config)); - - if (config.config == 0) break; - - S_scomList.scom = CENTAUR_DEVICE_ID; - S_scomList.commandType = GPE_SCOM_READ_VECTOR; - S_scomList.pData = G_centaurConfiguration.deviceId; - - S_parms.scomList = CAST_POINTER(uint64_t, &S_scomList); - S_parms.entries = 1; - S_parms.options = 0; - - pore_flex_create(&request, - &G_pore_gpe1_queue, - gpe_scom_centaur, - (uint32_t)(&S_parms), - SSX_MILLISECONDS(10), /* Timeout */ - 0, 0, 0); - - rc = pore_flex_schedule(&request); - - if (rc) break; - - while (!async_request_is_idle((AsyncRequest*)(&request))); - - if (!async_request_completed((AsyncRequest*)(&request)) || - (S_parms.rc != 0)) { - - PRINTD("gpe_scom_centaur() for CENTAUR_DEVICE_ID failed:\n" - " Async state = 0x%02x\n" - " gpe_scom_centaur() rc = %u\n" - " gpe_scom_centaur() errorIndex = %d\n", - ((AsyncRequest*)(&request))->state, - S_parms.rc, S_parms.errorIndex); - - rc = CENTAUR_READ_TPC_ID_FAILURE; - } - - if (0) { - - // Debug - - slvctl.value = G_gsc_lastSlaveControl; - - PRINTD("centaur_configuration_create:Debug\n" - " Last SCOM (PowerBus) address = 0x%016llx\n" - " Last Slave Control = 0x%016llx\n" - " Extended Address (positioned) = 0x%016llx\n" - " Last OCI Address = 0x%016llx\n", - G_gsc_lastScomAddress, - G_gsc_lastSlaveControl, - (unsigned long long)(slvctl.fields.extaddr) << - (64 - 23 - 14), - G_gsc_lastOciAddress); - } - - } while (0); - - // Copy the final RC into the global structure and done. - - memcpy_real(&(G_centaurConfiguration.configRc), &rc, sizeof(rc)); - - return rc; -} - - -// For now we have to handle configuring the PBA BAR and mask, and designating -// a SYNC if the firmware forgot to. - -int -centaur_configuration_create(void) -{ - return _centaur_configuration_create(PBA_BAR_CENTAUR, - PBA_SLAVE_PORE_GPE, - 2); -} - - -uint32_t mb_id(int i_mb) -{ - uint32_t rv; - centaur_device_id_t id; - - if ((i_mb < 0) || (i_mb >= PGP_NCENTAUR) || - (G_centaurConfiguration.configRc != 0)) { - - rv = (uint32_t)-1; - - } else { - - id.value = G_centaurConfiguration.deviceId[i_mb]; - rv = id.fields.cfam_id; - } - - return rv; -} - - -uint8_t mb_chip_type(int i_mb) -{ - uint8_t rv; - cfam_id_t id; - - if ((id.value = mb_id(i_mb)) == -1) { - - rv = (uint8_t)-1; - - } else { - - rv = id.chipType; - } - - return rv; -} - - -uint8_t mb_ec_level(int i_mb) -{ - uint8_t rv; - cfam_id_t id; - - if ((id.value = mb_id(i_mb)) == -1) { - - rv = (uint8_t)-1; - - } else { - - rv = (id.majorEc << 4) | id.minorEc; - } - - return rv; -} |