diff options
315 files changed, 46975 insertions, 0 deletions
diff --git a/src/ppe/LAYOUT b/src/ppe/LAYOUT new file mode 100644 index 0000000..38abdf6 --- /dev/null +++ b/src/ppe/LAYOUT @@ -0,0 +1,16 @@ +================================================================================ +-----------------------------PPE DIRECTORY STRUCTURE---------------------------- +================================================================================ + +sbe/ - FAPI-Lite SBE code to IPL the chip without the core and cache routine. + - May contain some PPE assembler files/functions. + +corecache/ - Core routines will also land in the CME image while cache routine will also land in the STOP GPE image. + - FAPI-Lite Hcode that initializes the core and cache chiplets. +pgpe/ - PState GPE code +ops/ - SBE chipOps -- may be delivered from the FW team but may have some early engineering forms +lib/ - FAPI-Lite Common PPE code routines (startclocks, arrayinit, etc) +pk/ - PPE Kernel + kernel/ - Base kernel + ppe42/ - Emulation function that don't exist in the PPE42 (div64, ppe_scom) +import/ - place for information about what needs to be mirrored into ppe build.
\ No newline at end of file diff --git a/src/ppe/hwp/cache/Makefile b/src/ppe/hwp/cache/Makefile new file mode 100644 index 0000000..115a69a --- /dev/null +++ b/src/ppe/hwp/cache/Makefile @@ -0,0 +1,54 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/hwp/cache/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 + +# This Makefile compiles all of the cache hardware procedure code. See the +# "cachehcdfiles.mk" file in this directory. + +#all generated files from this makefile will end up in obj/cache +export SUB_OBJDIR = /cache + +include img_defs.mk +include cachehcdfiles.mk + + +OBJS := $(addprefix $(OBJDIR)/, $(CACHE_OBJECTS)) + +libcache.a: cache + $(AR) crs $(OBJDIR)/libcache.a $(OBJDIR)/*.o + +.PHONY: clean cache +cache: $(OBJS) + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +clean: + rm -fr $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/hwp/cache/cachehcdfiles.mk b/src/ppe/hwp/cache/cachehcdfiles.mk new file mode 100644 index 0000000..28e36e7 --- /dev/null +++ b/src/ppe/hwp/cache/cachehcdfiles.mk @@ -0,0 +1,65 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/hwp/cache/cachehcdfiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file cachehcdfiles.mk +# +# @brief mk for including cache hcode object files +# +# @page ChangeLogs Change Logs +# @section cachehcdfiles.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# Object Files +########################################################################## + +CACHE-CPP-SOURCES += p9_hcd_cache_arrayinit.C +CACHE-CPP-SOURCES += p9_hcd_cache_chiplet_init.C +CACHE-CPP-SOURCES += p9_hcd_cache_chiplet_reset.C +CACHE-CPP-SOURCES += p9_hcd_cache_dpll_setup.C +CACHE-CPP-SOURCES += p9_hcd_cache_gptr_time_initf.C +CACHE-CPP-SOURCES += p9_hcd_cache_initf.C +CACHE-CPP-SOURCES += p9_hcd_cache_occ_runtime_scom.C +CACHE-CPP-SOURCES += p9_hcd_cache_poweron.C +CACHE-CPP-SOURCES += p9_hcd_cache_ras_runtime_scom.C +CACHE-CPP-SOURCES += p9_hcd_cache_repair_initf.C +CACHE-CPP-SOURCES += p9_hcd_cache_runinit.C +CACHE-CPP-SOURCES += p9_hcd_cache_scomcust.C +CACHE-CPP-SOURCES += p9_hcd_cache_scominit.C +CACHE-CPP-SOURCES += p9_hcd_cache_startclocks.C + +CACHE-C-SOURCES += +CACHE-S-SOURCES += + +CACHE_OBJECTS += $(CACHE-CPP-SOURCES:.C=.o) +CACHE_OBJECTS += $(CACHE-C-SOURCES:.c=.o) +CACHE_OBJECTS += $(CACHE-S-SOURCES:.S=.o) + diff --git a/src/ppe/hwp/cache/p9_hcd_cache.H b/src/ppe/hwp/cache/p9_hcd_cache.H new file mode 100644 index 0000000..6550690 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache.H @@ -0,0 +1,54 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache.H +/// @brief Cache Chiplet Procedure Includes +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_H__ +#define __P9_HCD_CACHE_H__ + +#include <p9_hcd_cache_arrayinit.H> +#include <p9_hcd_cache_chiplet_init.H> +#include <p9_hcd_cache_chiplet_reset.H> +#include <p9_hcd_cache_dpll_setup.H> +#include <p9_hcd_cache_gptr_time_initf.H> +#include <p9_hcd_cache_initf.H> +#include <p9_hcd_cache_occ_runtime_scom.H> +#include <p9_hcd_cache_poweron.H> +#include <p9_hcd_cache_ras_runtime_scom.H> +#include <p9_hcd_cache_repair_initf.H> +#include <p9_hcd_cache_runinit.H> +#include <p9_hcd_cache_scomcust.H> +#include <p9_hcd_cache_scominit.H> +#include <p9_hcd_cache_startclocks.H> + +#endif // __P9_HCD_CACHE_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_arrayinit.C b/src/ppe/hwp/cache/p9_hcd_cache_arrayinit.C new file mode 100644 index 0000000..465b413 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_arrayinit.C @@ -0,0 +1,170 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_arrayinit.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_arrayinit.C +/// @brief EX Initialize arrays +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Use ABIST engine to zero out all arrays +/// Upon completion, scan0 flush all rings +/// except Vital, Repair, GPTR, TIME and DPLL +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_arrayinit.H" + +//----------------------------------------------------------------------------- +// Constant Definitions +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Procedure: Initialize Cache Arrays +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_arrayinit( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + uint32_t scan; + uint32_t loop; + + // Procedure Prereq : P0 is pointing to the targeted EX chiplet + // submodules: + // seeprom_array_init_module + // ex_scan0 + + FAPI_INF("<p9_hcd_cache_arrayinit> : \ + *** Array Init and Scan0 Cleanup for EX Chiplets ***"); + + // SBE Address Base Register Setups + // Setup PRV_BASE_ADDR1; points to selected EX chiplet + // - mr P1, P0 + FAPI_INF("<p9_hcd_cache_arrayinit> : \ + Copy selected EX info from P0 to P1"); + + // Step 1: Array Init for selected EX chiplet + // ARRAY INIT module -> see p9_sbe_tp_array_init.S + // + // At entry: + // + // P1 : The chiplet ID/Multicast Group + // D1 : Clock Regions for Array Init + // + // At exit: + // + // P0, D0, D1, CTR : destroyed + // P1, A0, A1 : maintained + // + FAPI_INF("<p9_hcd_cache_arrayinit> : \ + Calling Array Init Subroutine"); + + // >>> IPL/Winkle + // \bug Need to exclude DPLL ring for IPL + // li D1, SCAN_ALLREGIONEXVITAL + // = li D1, SCAN_CLK_ALLEXDPLL + scan = SCAN_CLK_ALLEXDPLL; + + // Execute the array init + // = bsr seeprom_array_init_module + seeprom_array_init_module(scan); + + // Restore P0 with selected EX chiplet info + // - mr P0, P1 + FAPI_INF("<p9_hcd_cache_arrayinit> : \ + Copy selected EX info back from P1 to P0"); + + // Step 2: Scan0 for selected EX chiplet except PRV, GPTR, TIME and DPLL + FAPI_INF("<p9_hcd_cache_arrayinit> : \ + Calling Scan0 Subroutine"); + + // taken from p9_sbe_ex_chiplet_init + + // >>> IPL/Winkle scan flush - all except vital + + // Hook to bypass in Sim + // - hooki 0, 0xFF02 + // - ifslwcntlbitset P9_SLW_SKIP_FLUSH,1f + + FAPI_DBG("EX Init: Scan0 Module executed: \ + Scan all except vital, DPL, GPTR, and TIME scan chains"); + + // Each scan0 will rotate the ring 8191 latches (2**13 - 1) and the + // the longest ring is defined by P9_SCAN0_FUNC_REPEAT. When the design + // ALWAYS has all stumps less than 8191, the repeat (eg .rept) can be + // removed. + // Implementation note: this is not done in a loop (or included in the + // ex_scan0_module itself) as the D0 and D1 registers are used in + // ex_scan0_module and there is no convenient place to temporaily store + // the 2-64b values values. Argueably, PIBMEM could be used for this + // but was not utilized. + + // \bug remove DPLL ring + // ex_scan0 SCAN_ALL_BUT_VITALDPLLGPTRTIME, SCAN_CLK_ALL + // = .rept P9_SCAN0_FUNC_REPEAT + // = ex_scan0 SCAN_ALL_BUT_VITALDPLLGPTRTIME, SCAN_CLK_ALLEXDPLL + // = .endr + for(loop=0;loop<P9_SCAN0_FUNC_REPEAT;loop++) + { + ex_scan0(SCAN_ALL_BUT_VITALDPLLGPTRTIME,SCAN_CLK_ALLEXDPLL); + } + // - 1: + + FAPI_INF("<p9_hcd_cache_arrayinit> : \ + *** End of Procedure ***"); + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_arrayinit.H b/src/ppe/hwp/cache/p9_hcd_cache_arrayinit.H new file mode 100644 index 0000000..530c4db --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_arrayinit.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_arrayinit.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_arrayinit.H +/// @brief EX Initialize arrays +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_ARRAYINIT_H__ +#define __P9_HCD_CACHE_ARRAYINIT_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_arrayinit_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_arrayinit_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EX>&); + +/// @brief EX Initialize arrays +/// +/// @param [in] i_target TARGET_TYPE_EX target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_arrayinit( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_ARRAYINIT_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_chiplet_init.C b/src/ppe/hwp/cache/p9_hcd_cache_chiplet_init.C new file mode 100644 index 0000000..a73ad42 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_chiplet_init.C @@ -0,0 +1,140 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_chiplet_init.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_chiplet_init.C +/// @brief EX Flush/Initialize +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Scan0 flush all configured chiplet rings except Vital, GPTR, TIME and DPLL +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_chiplet_init.H" + +//----------------------------------------------------------------------------- +// Constant Definitions +//----------------------------------------------------------------------------- +//#define SIM_PLL +//#define SIM_SPEEDUP +////#define SCAN0_DISABLE +//#define STEP_CHIPLET_INIT_0 0x0 // Resetting DPLL +//#define STEP_CHIPLET_INIT_1 0x1 // Core+ECO glmux switch (IPL/Winkle) +//#define STEP_CHIPLET_INIT_2 0x2 // Core glmux switch (Sleep) +//#define STEP_CHIPLET_INIT_3 0x3 // Before Func flush for IPL/Winkle +//#define STEP_CHIPLET_INIT_4 0x4 // After Func flush for IPL/Winkle +//#define STEP_CHIPLET_INIT_5 0x5 // After Func flush for IPL/Winkle +//#define STEP_CHIPLET_INIT_6 0x6 // Before Core GPTR flush for Sleep +//#define STEP_CHIPLET_INIT_7 0x7 // After Core GPTR flush for Sleep +//#define STEP_CHIPLET_INIT_8 0x8 // Before Core Func flush for Sleep +//#define STEP_CHIPLET_INIT_9 0x9 // After Core Func flush for Sleep +//#define STEP_CHIPLET_INIT_A 0xA // Before Core Func flush for Sleep +//#define STEP_CHIPLET_INIT_B 0xB // After Core Func flush for Sleep +//#define PORE_REFCLK_CYCLES 1 // \todo need real value for hdw +//#define DPLL_LOCK_DELAY 8192*PORE_REFCLK_CYCLES + +//----------------------------------------------------------------------------- +// Procedure: EX Flush/Initialize +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_chiplet_init( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + uint32_t loop; + + // Procedure Prereq: + // p9_sbe_ex_chiplet_reset, p9_sbe_ex_dpll_initf, p9_sbe_ex_pll_initf + + FAPI_INF("<p9_hcd_cache_chiplet_init>: Entering procedure"); + + // Look for PSCOM error on any chip, fail if we find one + // scan0 flush all configured chiplet rings except EX DPLL + // call ex_scan0_module( ) + + // >>> IPL/Winkle scan flush - all except vital + + // Hook to bypass in Sim + // - hooki 0, 0xFF02 + // - ifslwcntlbitset P9_SLW_SKIP_FLUSH,1f + + FAPI_DBG("EX Init: Scan0 Module executed: \ + Scan all except vital, DPL, GPTR, and TIME scan chains"); + // - updatestep STEP_CHIPLET_INIT_6, D0, P1 + + // Each scan0 will rotate the ring 8191 latches (2**13 - 1) and the + // the longest ring is defined by P9_SCAN0_FUNC_REPEAT. When the design + // ALWAYS has all stumps less than 8191, the repeat (eg .rept) can be + // removed. + // Implementation note: this is not done in a loop (or included in the + // ex_scan0_module itself) as the D0 and D1 registers are used in + // ex_scan0_module and there is no convenient place to temporaily store + // the 2-64b values values. Argueably, PIBMEM could be used for this + // but was not utilized. + // = .rept P9_SCAN0_FUNC_REPEAT + // = ex_scan0 SCAN_ALL_BUT_VITALDPLLGPTRTIME, SCAN_CLK_ALLEXDPLL + // = .endr + for(loop=0;loop<P9_SCAN0_FUNC_REPEAT;loop++) + { + ex_scan0(SCAN_ALL_BUT_VITALDPLLGPTRTIME,SCAN_CLK_ALLEXDPLL); + } + // - updatestep STEP_CHIPLET_INIT_7, D0, P1 + // - 1: + + FAPI_INF("<p9_hcd_cache_chiplet_init>: Exiting procedure"); + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_chiplet_init.H b/src/ppe/hwp/cache/p9_hcd_cache_chiplet_init.H new file mode 100644 index 0000000..8dfacbc --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_chiplet_init.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_chiplet_init.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_chiplet_init.H +/// @brief EX Flush/Initialize +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_CHIPLET_INIT_H__ +#define __P9_HCD_CACHE_CHIPLET_INIT_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_chiplet_init_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_chiplet_init_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>&); + + +/// @brief EX Flush/Initialize +/// +/// @param [in] i_target TARGET_TYPE_EQ target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_chiplet_init( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_CHIPLET_INIT_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_chiplet_reset.C b/src/ppe/hwp/cache/p9_hcd_cache_chiplet_reset.C new file mode 100644 index 0000000..a4fa4ce --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_chiplet_reset.C @@ -0,0 +1,313 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_chiplet_reset.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_chiplet_reset.C +/// @brief Cache Chiplet Reset +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Reset quad chiplet logic +/// Scan0 flush entire cache chiplet +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_chiplet_reset.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ + +// GP3 Bits +// 1 - PCB_EP_RESET +// 2 - GLMMUX Reset +// 3 - PLL_TEST Enable +// 4 - PLLRST - PLL Reset +// 5 - PLL Bypass +// 11 - D_MODE for Vital +// 13 - MPW2 for Vital +// 14 - PMW1 for Vital +// 18 - FENCE_EN for chiplet +// 22 - Resonant Clock disable +// 23:24 - Glitchless Mux Sel +// 25: - ?? (set because System Pervasive flow does this) +// Background: system pervasive as the following setting in their tests: +// 7C1623C000000000 +// Bits set: +// 1, 2, 3, 4, 5, 11, 13, 14, 18, 22, 23, 24, 25 +//#define GP3_INIT_VECTOR (BITS(1,5)|BIT(11)|BIT(13)|BIT(14)|BIT(18)|BIT(22)|BIT(23)|BIT(24)|BIT(25)) + +// hang counter inits +//#define HANG_P1_INIT 0x0400000000000000 +//#define PCB_SL_ERROR_REG_RESET 0xFFFFFFFFFFFFFFFF +//#define STEP_CHIPLET_RESET_1 0x1 // After start of vital clocks +//#define STEP_CHIPLET_RESET_2 0x2 // After fence drop +//#define STEP_CHIPLET_RESET_3 0x3 // Before GPTR flush for IPL/Winkle +//#define STEP_CHIPLET_RESET_4 0x4 // After GPTR flush for IPL/Winkle +//#define STEP_CHIPLET_RESET_5 0x5 // Before Func flush for IPL/Winkle +//#define STEP_CHIPLET_RESET_6 0x6 // After Func flush for IPL/Winkle +//#define STEP_CHIPLET_RESET_7 0x7 // Before GPTR flush for Sleep +//#define STEP_CHIPLET_RESET_8 0x8 // After GPTR flush for Sleep + +//------------------------------------------------------------------------------ +// Procedure: Cache Chiplet Reset +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_chiplet_reset( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target) +{ + +#if 0 + uint32_t loop; + + ///////////////////////////////////////////////////////////////// + // repeat some init steps of chiplet_init + ///////////////////////////////////////////////////////////////// + + // If there is a unused, powered-off EX chiplet which needs to be + // configured in the following steps to setup the PCB endpoint. + + // Skip the PCB endpoint config steps for sleep so that fences don't + // get dropped (eg by dropping chiplet_enable (GP3(0)). + + FAPI_INF("<p9_hcd_cache_chiplet_reset>: \ + Repeat dedicated pervasive init steps for EX "); + + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + Reset GP3 for EX chiplet, step needed for hotplug"); + // = sti GENERIC_GP3_0x000F0012,P0,GP3_INIT_VECTOR + FAPI_TRY(putScom(i_target, GENERIC_GP3_0x000F0012, + fapi2:buffer<uint64_t>(23452345))); + + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + Drop aync reset to Glitchless Mux"); + // = sti GENERIC_GP3_AND_0x000F0013,P0,~BIT(2) + FAPI_TRY(putScom(i_target, GENERIC_GP3_AND_0x000F0013, + fapi2:buffer<uint64_t>().flush<1>().clearBit<2>())); + + // 19:21 PM_PI_DECODE needs to be 010 for functional operation(set bit 20) + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + Put DPLL in functional mode"); + // = sti GENERIC_GP3_OR_0x000F0014,P0, BIT(20) + FAPI_TRY(putScom(i_target, GENERIC_GP3_OR_0x000F0014, + fapi2::buffer<uint64_t>().setBit<20>())); + + // - updatestep STEP_CHIPLET_RESET_1, D0, P1 + + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + Release endpoint reset for PCB"); + // = sti GENERIC_GP3_AND_0x000F0013,P0,~BIT(1) + FAPI_TRY(putScom(i_target, GENERIC_GP3_AND_0x000F0013, + fapi2:buffer<uint64_t>().flush<1>().clearBit<1>())); + + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + Partial good setting"); + // = sti GENERIC_GP3_OR_0x000F0014,P0,BIT(0) + FAPI_TRY(putScom(i_target, GENERIC_GP3_OR_0x000F0014, + fapi2::buffer<uint64_t>().setBit<0>())); + + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + PCB slave error reg reset"); + // = sti MASTER_PCB_ERR_0x000F001F,P0,PCB_SL_ERROR_REG_RESET + FAPI_TRY(putScom(i_target, MASTER_PCB_ERR_0x000F001F, + fapi2:buffer<uint64_t>(643564))); + + FAPI_DBG("Use timer mode for DPLL lock when enabled"); + // = sti EX_PMGP0_OR_0x100F0102, P0, BIT(7) + FAPI_TRY(putScom(i_target, EX_PMGP0_OR_0x100F0102, + fapi2::buffer<uint64_t>().setBit<7>())); + + // Set the DPLL Timer value for waiting on DPLL HOLDs in 35:36 + // 00 = 1024 cycles <---- + // 01 = 512 cycles + // 10 = 256 cycles + // 11 = 128 cycles + FAPI_DBG("Set the timer value for waiting on DPLL THOLDs"); + // = sti EX_PMGP0_AND_0x100F0101,P0,~(BIT(35)|BIT(36)) + FAPI_TRY(putScom(i_target, EX_PMGP0_AND_0x100F0101, + fapi2:buffer<uint64_t>().flush<1>().insertFromRight<35,2>(0))); + + // Only perform the disablement of PCBS-PM for the IPL work-around when + // doing IPL (eg skip if winkle; this whole section is skipped for sleep) + // >>> IPL + // FAPI_DBG("Disable the PCBS-PM as part of winkle enablement"); + // = sti EX_PMGP0_OR_0x100F0102, P0, BIT(0) + FAPI_TRY(putScom(i_target, EX_PMGP0_OR_0x100F0102, + fapi2:buffer<uint64_t>().setBit<0>())); + + // The following is performed for both IPL/Winkle and Sleep + + // Note: These are executed for sleep as well as these fences will have + // already been dropped + + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + Remove pervasive ECO fence;"); + // ECO Fence in 22 + // = sti EX_PMGP0_AND_0x100F0101,P0,~(BIT(22)) + FAPI_TRY(putScom(i_target, EX_PMGP0_AND_0x100F0101, + fapi2:buffer<uint64_t>().flush<1>().clearBit<22>())); + + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + Remove winkle mode before scan0 on EX chiplets is executed"); + // PM Exit States: WINKLE_EXIT_DROP_ELEC_FENCE + + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + Remove logical pervasive/pcbs-pm fence"); + // = sti EX_PMGP0_AND_0x100F0101,P0,~(BIT(39)) + FAPI_TRY(putScom(i_target, EX_PMGP0_AND_0x100F0101, + fapi2:buffer<uint64_t>().flush<1>().clearBit<39>())); + + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + Remove PB Winkle Electrical Fence GP3(27)"); + // = sti EX_GP3_AND_0x100F0013,P0,~(BIT(27)) + FAPI_TRY(putScom(i_target, EX_GP3_AND_0x100F0013, + fapi2:buffer<uint64_t>().flush<1>().clearBit<27>())); + + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + Configuring chiplet hang counters") ; + // = sti EX_HANG_P1_0x100F0021,P0,HANG_P1_INIT + data = 34654; // HANG_P1_INIT + FAPI_TRY(putScom(i_target, EX_HANG_P1_0x100F0021, + fapi2:buffer<uint64_t>(34654))); + // - updatestep STEP_CHIPLET_RESET_2, D0, P1 + + ////////////////////////////////////////////////////////////// + // perform scan0 module for pervasive chiplet (GPTR_TIME_REPR) + ////////////////////////////////////////////////////////////// + + // >>> IPL/Winkle scan flush - core and EX + + // Hook to bypass in sim while providing a trace + // - hooki 0, 0xFF01 + // - ifslwcntlbitset P9_SLW_SKIP_FLUSH,1f + + // \todo WORKAROUND UNTIL LOGIC CHANGES + // Drop the core2cache and cache2core fences to allow for L2 scanning + FAPI_DBG("<p9_hcd_cache_chiplet_reset>: \ + Remove pervasive ECO fence;"); + // = sti EX_PMGP0_AND_0x100F0101,P0,~(BIT(20) | BIT(21)) + FAPI_TRY(putScom(i_target, EX_PMGP0_AND_0x100F0101, + fapi2:buffer<uint64_t>().flush<1>().insertFromRight<20,2>(0))); + + FAPI_DBG("EX Reset: Scan0 Module executed: \ + Scan the GPTR/TIME/REP rings"); + // - updatestep STEP_CHIPLET_RESET_3, D0, P1 + + // = .rept P9_SCAN0_GPTR_REPEAT + // = ex_scan0 SCAN_GPTR_TIME_REP, SCAN_CLK_ALL + // = .endr + for(loop=0;loop<P9_SCAN0_GPTR_REPEAT;loop++) + { + ex_scan0(SCAN_GPTR_TIME_REP, SCAN_CLK_ALL); + } + + // - updatestep STEP_CHIPLET_RESET_4, D0, P1 + + // - 1: + // Hook to bypass in sim while providing a trace + // - hooki 0, 0xFF02 + // - ifslwcntlbitset P9_SLW_SKIP_FLUSH,1f + + FAPI_DBG("EX Reset: Scan0 Module executed: \ + Scan the all but GPTR/TIME/REP rings"); + // - updatestep STEP_CHIPLET_RESET_5, D0, P1 + + // Each scan0 will rotate the ring 8191 latches (2**13 - 1) and the + // the longest ring is defined by P9_SCAN0_FUNC_REPEAT. When the design + // ALWAYS has all stumps less than 8191, the repeat (eg .rept) can be + // removed. + // Implementation note: this is not done in a loop (or included in the + // ex_scan0_module itself) as the D0 and D1 registers are used in + // ex_scan0_module and there is no convenient place to temporarily store + // the 2-64b values values. Argueably, PIBMEM could be used for this + // but was not utilized. + // = .rept P9_SCAN0_FUNC_REPEAT + // = ex_scan0 SCAN_ALL_BUT_GPTRTIMEREP, SCAN_CLK_ALL + // = .endr + for(loop=0;loop<P9_SCAN0_FUNC_REPEAT;loop++) + { + ex_scan0(SCAN_ALL_BUT_GPTRTIMEREP, SCAN_CLK_ALL); + } + + // - updatestep STEP_CHIPLET_RESET_6, D0, P1 + + // Ensure CC interrupts are disabled before starting clock domains and dpll + // But only do it for Murano-DD1.x! + // - lpcs P1, STBY_CHIPLET_0x00000000 + // - ldandi D0, PCBMS_DEVICE_ID_0x000F000F, P1, BITS(0, 32) + // - andi D0, D0, CFAM_CHIP_ID_CHIP_MAJOR_MASK + // - cmpibrane D0, 1f, CFAM_CHIP_ID_MURANO_1 + + // - mr A0, P0 + // - mr D1, ETR + // - ls P0, CHIPLET0 + // - ls CTR, MAX_CORES + // - bra end_core_loop + + // - begin_core_loop: + // Inspect presence of current ex chiplet + // - andi D0, D1, BIT(32) + // - braz D0, continue_core + // Disable CC interrupts. + // - ld D0, EX_SYNC_CONFIG_0x10030000, P0 + // - ori D0, D0, BIT(6) + // - std D0, EX_SYNC_CONFIG_0x10030000, P0 + + // - continue_core: + // - adds P0, P0, 1 //Increment ex chiplet + // - rols D1, D1, 1 //Shift ex chiplet mask left + + // - end_core_loop: + // - loop begin_core_loop + // - mr P0, A0 + // - 1: + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_chiplet_reset.H b/src/ppe/hwp/cache/p9_hcd_cache_chiplet_reset.H new file mode 100644 index 0000000..8dc6167 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_chiplet_reset.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_chiplet_reset.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_chiplet_reset.H +/// @brief Cache Chiplet Reset +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_CHIPLET_RESET_H__ +#define __P9_HCD_CACHE_CHIPLET_RESET_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_chiplet_reset_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_chiplet_reset_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>&); + +/// @brief Cache Chiplet Reset +/// +/// @param [in] i_target TARGET_TYPE_EQ target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_chiplet_reset( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_CHIPLET_RESET_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_dpll_setup.C b/src/ppe/hwp/cache/p9_hcd_cache_dpll_setup.C new file mode 100644 index 0000000..0175c98 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_dpll_setup.C @@ -0,0 +1,282 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_dpll_setup.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_dpll_setup.C +/// @brief Quad DPLL Setup +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Initfiles in procedure defined on VBU ENGD wiki (TODO add link) +/// DPLL tune bits are not dependent on frequency +/// Put DPLL into bypass +/// Set DPLL syncmux sel +/// Set clock controller scan ratio to 1:1 as this is done at refclk speeds +/// Load the EX DPLL scan ring +/// Set clock controller scan ratio to 8:1 for future scans +/// Frequency is controlled by the Quad PPM +/// Actual frequency value for boot is stored into the Quad PPM by +/// p9_hcd_setup_evid.C in istep 2 +/// In real cache STOP exit, the frequency value is persistent +/// Enable the DPLL in the correct mode +/// non-dynamic +/// Slew rate established per DPLL team +/// Take the cache glitchless mux out of reset +/// (TODO: is there still a reset on P9?) +/// Remove DPLL bypass +/// Drop DPLL Tholds +/// Check for DPLL lock +/// Timeout: 200us +/// Switch cache glitchless mux to use the DPLL +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_dpll_setup.H" + +//----------------------------------------------------------------------------- +// Constant Definitions +//----------------------------------------------------------------------------- + +//#define DPLL_LOCK_BIT, 50 +//#define DPLL_LOCK_MAX_POLL_LOOPS, 0x1600 +//#define DPLL_LOCK_DELAY_CYCLES, 0x10 +//#define STEP_SBE_DPLL_SETUP_LOCK, 1 +//#define STEP_SBE_DPLL_GMUX_SET, 2 +//#define STEP_SBE_DPLL_SETUP_COMPLETE, 3 + +// For a 2000GHz nest (500MHz Pervasive), 2ns clocks exists +// For a DPLL lock time of >150us from power on, 150000/2 = 75000 +// d75000 => 0x124F8 ----> round up to 0x15000 + +// For a 2400GHz nest (600MHz Pervasive), 1.667ns clocks exists +// For a DPLL lock time of >150us from power on, 150000/1.667 = 89982 +// d90000 => 0x15f90 ----> round up to 0x16000 + +//#define DPLL_LOCK_DELAY 0x10 +//#define DPLL_LOCK_LOOP_NUMBER 0x1600 + +//#define ex_dpll_lock_delay_mult 0x1600 +//#define ex_glsmux_post_delay_mult 0x1 + +//----------------------------------------------------------------------------- +// Procedure: Quad DPLL Setup +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_dpll_setup( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + FAPI_INF("EX Chiplet -> Start DPLL setup" ) + + // The setup of P0 happens external to this procedure + // P0 is set to point to either a single EX core, or to multiple EX + // cores using multicast + FAPI_DBG("EX Chiplet dpll_setup P0 -> 0x%02llx" , io_pore.p0.read()) + + // Skip DPLL and Glitchless mux setup for Sleep + // Glitchless mux change for the core (Sleep) done in + // p9_sbe_ex_chiplet_reset. + + // - ifsleep D0, glm_end + // >>> IPL/WINKLE + + // - dpll_start: + + // - setp1_mcreadand D0 + + FAPI_INF("Set up CPM PARM register for DPLL") + // = ld D0, EX_DPLL_CPM_PARM_REG_0x100F0152, P1 + FAPI_TRY(getScom(i_target, EX_DPLL_CPM_PARM_REG_0x100F0152, data)); + + // ----- Make sure that ff_bypass is set to "1" ----- + // This is necessary to ensure that the DPLL is in Mode 1. If not, + // the lock times will go from ~30us to 3-5ms + // Set bit 11 of DPLL Mode register 0x150F0152 + + FAPI_DBG("Put DPLL into Mode 1 by asserting ff_bypass.") + FAPI_DBG(">>> Work around <<<<: Also disabling ping-pong synchronizer" ) + // = ori D0, D0, (BIT(11)|BIT(32)) + data.setBit<11>().setBit<32>(); + + FAPI_DBG("Clear bits 15,16,18-23 and set bit 17 of DPLL reg 0x10F0152") + // = andi D0, D0, 0xFFFE00FFFFFFFFFF + // = ori D0, D0, BIT(17) + data.insertFromRight<15,9>(0x40); + + FAPI_DBG("Set slew rate to a modest value") + // = ori D0, D0, 0x8000000000000000 + // = std D0, EX_DPLL_CPM_PARM_REG_0x100F0152, P0 + data.setBit<0>(); + FAPI_TRY(putScom(i_target, EX_DPLL_CPM_PARM_REG_0x100F0152, data)); + + // ----- Clear dpllclk_muxsel (syncclk_muxsel) to "0" ----- + FAPI_INF("Reset syncclk_muxsel or dpllclk_muxsel") + // = sti GENERIC_GP0_AND_0x00000004, P0, ~BIT(1) + FAPI_TRY(putScom(i_target, GENERIC_GP0_AND_0x00000004, + fapi2:buffer<uint64_t>().flush<1>().clearBit<1>())); + + // = sti EX_PMGP0_AND_0x100F0101, P0, ~(BIT(11)) + FAPI_TRY(putScom(i_target, EX_PMGP0_AND_0x100F0101, + fapi2:buffer<uint64_t>().flush<1>().clearBit<11>())); + + // ----- Take DPLL out of bypass ----- + // Clear bit 5 of EX GP3 Register + FAPI_INF("EX Chiplet -> Take DPLL out of bypass" ) + // = sti EX_GP3_AND_0x100F0013, P0, ~(BIT(5)) + FAPI_TRY(putScom(i_target, EX_GP3_AND_0x100F0013, + fapi2:buffer<uint64_t>().flush<1>().clearBit<5>())); + + // ----- Drop DPLL tholds ----- + // Clear bit 3 of EX PMGP0 Register + FAPI_INF("EX Chiplet -> Drop internal DPLL THOLD" ) + // = sti EX_PMGP0_AND_0x100F0101, P0, ~(BIT(3)) + FAPI_TRY(putScom(i_target, EX_PMGP0_AND_0x100F0101, + fapi2:buffer<uint64_t>().flush<1>().clearBit<3>())); + + // ----- Delay to wait for DPLL to lock ----- + // TODO: Determine whether or not we should POLL instead of put delay here. + // Wait for >150us + + FAPI_INF("Wait for DPLL to lock" ) + // - waits DPLL_LOCK_LOOP_NUMBER*DPLL_LOCK_DELAY + + // Check for lock + // - ldandi D0, EX_PMGP0_0x100F0100, P1, BIT(DPLL_LOCK_BIT) + // - braz D0, dpll_nolock + + // ----- Recycle DPLL in and out of bypass ----- + // Clear bit 5 of EX GP3 Register + FAPI_INF("EX Chiplet -> Recycle DPLL in and out of bypass" ) + // = sti EX_GP3_OR_0x100F0014, P0, BIT(5) + FAPI_TRY(putScom(i_target, EX_GP3_OR_0x100F0014, + fapi2:buffer<uint64_t>().setBit<5>())); + + // = sti EX_GP3_AND_0x100F0013, P0, ~(BIT(5)) + FAPI_TRY(putScom(i_target, EX_GP3_AND_0x100F0013, + fapi2:buffer<uint64_t>().flush<1>().clearBit<5>())); + + FAPI_INF("EX Chiplet -> EX DPLL is locked" ) + // - updatestep STEP_SBE_DPLL_SETUP_LOCK, D0, P1 + + // - glm_start: + + // ----- Set Glitch-Less MUXes for IPL/Winkle case ---- + // For Sleep, the core glitchless mux is change earlier as the DPLL + // was already up and locked. + // + // Set various gl muxes to pass the output of the DPLLs to the clock grid. + + // Read-modify-write (vs sti AND and sti OR) is done so that glitchless + // mux change field change is atomic (eg 1 store) + // - setp1_mcreadand D1 + + // = ld D1,EX_PMGP0_0x100F0100,P1 + FAPI_TRY(getScom(i_target, EX_PMGP0_0x100F0100, data)); + + // IPL/Winkle - Switch glitchless mux primary source to 001 = DPLL for bits + // 27:29 + + // Note: GLM async reset occured in p9_sbe_ex_chiplet_reset. + + // Set tp_clkglm_sel_dc to "001" (EX PM GP0 bits 27-29) + FAPI_INF("EX Chiplet -> Set glitchless mux select for primary chiplet clock source to 001 ") + // Set tp_clkglm_eco_sel_dc to "0" (EX PM GP0 bit 30) + // Set the core glitchless mux to use the primary input (b00). + // EX PM GP0 bits 32-33) + FAPI_INF("EX Chiplet -> Set glitchless mux select for core and eco domain to 0 ") + // = andi D1, D1, ~(BIT(27)|BIT(28)|BIT(30)|BIT(32)|BIT(33)) + // = ori D1, D1, (BIT(29)) + data.insertFromRight<27,4>(0x2).inerstFromRight<32,2>(0x0); + + // Store the final result to the hardware + // = std D1,EX_PMGP0_0x100F0100,P0 + FAPI_TRY(putScom(i_target, EX_PMGP0_0x100F0100, data)); + + // - glm_end: + + // - updatestep STEP_SBE_DPLL_GMUX_SET, D0, P1 + + // ----- Drop ff_bypass to enable slewing ----- + // ----- (Change from Mode 1 to mode 2) ----- + // Clear bit 11 of DPLL Mode register 0x150F0152 + // CMO20131125-Further, drop the pp synchronizer bit32. + // CMO20131219-Keep the pp sync bit32 asserted to avoid x-leakage(HW276931). + FAPI_INF("EX Chiplet -> Clear ff_bypass to switch into slew-controlled mode") + // - setp1_mcreadand D1 + // = ld D1, EX_DPLL_CPM_PARM_REG_0x100F0152, P1 + // = andi D1, D1, ~(BIT(11)) + // = std D1, EX_DPLL_CPM_PARM_REG_0x100F0152, P0 + FAPI_TRY(getScom(i_target, EX_DPLL_CPM_PARM_REG_0x100F0152, data)); + data.clearBit<11>(); + FAPI_TRY(putScom(i_target, EX_DPLL_CPM_PARM_REG_0x100F0152, data)); + + // ----- Drop other tholds ----- + // Clear bit 3 of EX PM GP0 Register + // FAPI_INF("EX Chiplet -> Drop DPLL thold" ) + // sti EX_PMGP0_AND_0x100F0101,P0, ~(BIT(3)) + + // - updatestep STEP_SBE_DPLL_SETUP_COMPLETE, D0, P1 + FAPI_INF("EX Chiplet -> DPLL setup completed" ) + + // DEBUG only + // - setp1_mcreadand D1 + // = ld D0,EX_GP0_0x10000000,P1 + FAPI_TRY(getScom(i_target, EX_GP0_0x10000000, data)); + + // - dpll_nolock: + FAPI_ERR("EX_DPLL -> Failed to lock"); + // - reqhalt RC_SBE_DPLL_SETUP_NOLOCK + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_dpll_setup.H b/src/ppe/hwp/cache/p9_hcd_cache_dpll_setup.H new file mode 100644 index 0000000..df13cf0 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_dpll_setup.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_dpll_setup.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_dpll_setup.H +/// @brief Quad DPLL Setup +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_DPLL_SETUP_H__ +#define __P9_HCD_CACHE_DPLL_SETUP_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_dpll_setup_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_dpll_setup_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>&); + +/// @brief Quad DPLL Setup +/// +/// @param [in] i_target TARGET_TYPE_EQ target +/// +/// @attr +/// @attritem ATTR_DPLL_REPAIR_RING - EQ target, uint32 +/// repair dpll ring content<br> +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_dpll_setup( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_DPLL_SETUP_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_gptr_time_initf.C b/src/ppe/hwp/cache/p9_hcd_cache_gptr_time_initf.C new file mode 100644 index 0000000..498ae79 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_gptr_time_initf.C @@ -0,0 +1,110 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_gptr_time_initf.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_gptr_time_initf.C +/// @brief Load GPTR and Time for EX non-core +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Initfiles in procedure defined on VBU ENGD wiki (TODO add link) +/// to produce #G VPD contents +/// Check for the presence of core override GPTR ring from image +/// (this is new fvor P9) +/// if found, apply; if not, apply core GPTR from image +/// Check for the presence of core override TIME ring from image; +/// if found, apply; if not, apply core base TIME from image +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_gptr_time_initf.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Procedure: Load GPTR and Time for EX non-core +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_gptr_time_initf( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target) +{ + +#if 0 + + // Set EX scan ratio to 1:1 as EX is still at refclock + FAPI_INF("<p9_sbe_ex_gptr_time_initf> : Set EX scan ratio to 1:1 ..."); + // = sti EX_OPCG_CNTL0_0x10030002, P0, 0x0 + FAPI_TRY(fapi2::putScom(i_target, EX_OPCG_CNTL0_0x10030002, 0x0)); + + // scan ring content shared among all chiplets + FAPI_DBG("Scanning EX GPTR rings...") + // - load_ring ex_gptr_perv skipoverride=1 + // - load_ring ex_gptr_dpll skipoverride=1 + // - load_ring ex_gptr_l3 skipoverride=1 + // - load_ring ex_gptr_l3refr skipoverride=1 + + // scan chiplet specific ring content + FAPI_DBG("Scanning EX TIME rings...") + // - load_ring_vec_ex ex_time_eco + + + // Set EX scan ratio back to 8:1 + FAPI_INF("<p9_sbe_ex_gptr_time_initf> : Set EX scan ratio to 8:1 ..."); + // Inputs: A1 and P0 and D0, destroys D0 & D1 + // - .pibmem_port (PORE_SPACE_PIBMEM & 0xf) + // - lpcs P1, PIBMEM0_0x00080000 + // - ld D0, ex_scan_ratio_override, P1 + // - bsr set_scan_ratio_d0 + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_gptr_time_initf.H b/src/ppe/hwp/cache/p9_hcd_cache_gptr_time_initf.H new file mode 100644 index 0000000..17d001f --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_gptr_time_initf.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_gptr_time_initf.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_gptr_time_initf.H +/// @brief Load GPTR and Time for EX non-core +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_GPTR_TIME_INIT_H__ +#define __P9_HCD_CACHE_GPTR_TIME_INIT_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_gptr_time_initf_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_gptr_time_initf_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>&); + +/// @brief Load GPTR and Time for EX non-core +/// +/// @param [in] i_target TARGET_TYPE_EQ target +/// +/// @attr +/// @attritem ATTR_CACHE_GPTR_TIME_RING - EX target, uint32 +/// pointer to RS4 content.<br> +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_gptr_time_initf( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_GPTR_TIME_INIT_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_initf.C b/src/ppe/hwp/cache/p9_hcd_cache_initf.C new file mode 100644 index 0000000..630940b --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_initf.C @@ -0,0 +1,99 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_initf.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_initf.C +/// @brief EX (non-core) scan init +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Initfiles in procedure defined on VBU ENGD wiki (TODO add link) +/// Check for the presence of cache FUNC override rings from image; +/// if found, apply; if not, apply cache base FUNC rings from image +/// Note: FASTINIT ring (eg CMSK ring) is setup at this point to limit the +/// stumps that participate in FUNC ring scanning (this is new for P9). +/// (TODO to make sure the image build support is in place) +/// Note: all caches that are in the Cache Multicast group will be +/// initialized to the same values via multicast scans +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_initf.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Procedure: EX (non-core) scan init +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_initf( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + // - load_ring ex_lbst_eco conditional_override=1 + // - load_ring ex_abfa_eco conditional_override=1 + // - load_ring ex_cmsk_eco conditional_override=1 + // - load_ring ex_func_perv conditional_override=1 + // - load_ring ex_func_l3 conditional_override=1 + // - load_ring ex_func_l3refr conditional_override=1 + + //Sim Speedup for L3 refresh cycles + // - load_ring ex_regf_l3 conditional_override=1 + // - load_ring ex_regf_l3refr conditional_override=1 + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_initf.H b/src/ppe/hwp/cache/p9_hcd_cache_initf.H new file mode 100644 index 0000000..9f7ffdc --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_initf.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_initf.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_initf.H +/// @brief EX (non-core) scan init +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_INITF_H__ +#define __P9_HCD_CACHE_INITF_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_initf_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_initf_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EX>&); + +/// @brief EX (non-core) scan init +/// +/// @param [in] i_target TARGET_TYPE_EX target +/// +/// @attr +/// @attritem ATTR_CACHE_L2_FUNC_RING - EX target, uint32 +/// @attritem ATTR_CACHE_L3_FUNC_RING - EX target, uint32 +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_initf( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_INITF_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_occ_runtime_scom.C b/src/ppe/hwp/cache/p9_hcd_cache_occ_runtime_scom.C new file mode 100644 index 0000000..8e1c82e --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_occ_runtime_scom.C @@ -0,0 +1,93 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_occ_runtime_scom.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_occ_runtime_scom.C +/// @brief EX OCC runtime scoms +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Run-time updates from OCC code that are put somewhere TBD +/// (TODO . revisit with OCC FW team) +/// OCC FW sets up value in the TBD SCOM section +/// This was not leverage in P8 with the demise of CPMs +/// Placeholder at this point +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_occ_runtime_scom.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ +#define host_runtime_scom 0 + +//------------------------------------------------------------------------------ +// Procedure: EX OCC runtime SCOMS +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_occ_runtime_scom( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + // Run the SCOM sequence if the SCOM procedure is defined + // - la A0, occ_runtime_scom + // - ld D0, 0, A0 + // - braz D0, 1f + FAPI_INF("Launching OCC Runtime SCOM routine") + // - bsrd D0 + // - 1: + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_occ_runtime_scom.H b/src/ppe/hwp/cache/p9_hcd_cache_occ_runtime_scom.H new file mode 100644 index 0000000..e82b6b2 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_occ_runtime_scom.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_occ_runtime_scom.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_occ_runtime_scom.H +/// @brief EX OCC runtime scoms +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_OCC_RUNTIME_SCOM_H__ +#define __P9_HCD_CACHE_OCC_RUNTIME_SCOM_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_occ_runtime_scom_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_occ_runtime_scom_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EX>&); + + +/// @brief EX OCC runtime scoms +/// +/// @param [in] i_target TARGET_TYPE_EX target +/// +/// @attr +/// @attritem ATTR_CACHE_OCC_SCOM_LOC - EX target, uint32 +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_occ_runtime_scom( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_OCC_RUNTIME_SCOM_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_poweron.C b/src/ppe/hwp/cache/p9_hcd_cache_poweron.C new file mode 100644 index 0000000..0aa81a1 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_poweron.C @@ -0,0 +1,84 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_poweron.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_poweron.C +/// @brief Cache Chiplet Power-on +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Command the cache PFET controller to power-on +/// Check for valid power on completion +/// Polled Timeout: 100us +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_poweron.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Procedure: Cache Chiplet Power-on +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_poweron( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target, + const uint32_t i_operation) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_poweron.H b/src/ppe/hwp/cache/p9_hcd_cache_poweron.H new file mode 100644 index 0000000..89bcffc --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_poweron.H @@ -0,0 +1,66 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_poweron.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_poweron.H +/// @brief Cache Chiplet Power-on +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_POWERON_H__ +#define __P9_HCD_CACHE_POWERON_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_poweron_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_poweron_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>&, + const uint32_t); + + +/// @brief Cache Chiplet Power-on +/// +/// @param [in] i_target TARGET_TYPE_EQ target +/// @param [in] i_operation ENUM(ON,OFF) +/// +/// @attr +/// @attritem ATTR_PFET_* +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_poweron( + const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target, + const uint32_t i_operation); + + +} // extern C + +#endif // __P9_HCD_CACHE_POWERON_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_ras_runtime_scom.C b/src/ppe/hwp/cache/p9_hcd_cache_ras_runtime_scom.C new file mode 100644 index 0000000..88a0518 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_ras_runtime_scom.C @@ -0,0 +1,171 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_ras_runtime_scom.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_ras_runtime_scom.C +/// @brief EX FSP/Host runtime scoms +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Run-time updates by FSP/Host(including HostServices and Hypervisors) +/// that are put on the cache image by STOP API calls +/// Dynamically built pointer where a NULL is checked before execution +/// If NULL (the SBE case), return +/// Else call the function at the pointer; pointer is filled in by +/// STOP image build +/// Powerbus (MCD) and L3 BAR settings +/// Runtime FIR mask updates from PRD +/// L2/L3 Repairs +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_ras_runtime_scom.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ +#define host_runtime_scom 0 + +//------------------------------------------------------------------------------ +// Procedure: EX FSP/HOST runtime scoms +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_ras_runtime_scom( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + // Run the SCOM sequence if the SCOM procedure is defined + // - la A0, sp_runtime_scom + // - ld D0, 0, A0 + // - braz D0, 1f + //FAPI_INF("Launching SP Runtime SCOM routine") + // - bsrd D0 + // - 1: + // + + // Run the SCOM sequence if the SCOM procedure is defined. + // - la A0, host_runtime_scom + // - ld D1, 0, A0 + // - braz D1, 1f + + // Prep P1 + // - setp1_mcreadand D0 + +#if 0 + // Disable the AISS to allow the override + // = ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + // = andi D0, D0, ~(BIT(1)) + // = std D0, EX_OHA_MODE_REG_RWx1002000D, P0 + // Drop PSCOM fence to allow SCOM and set pm_wake-up to PC to accepts + // RAMs (SCOMs actually) in the IPL "Nap" state + // = ld D0, EX_OHA_AISS_IO_REG_0x10020014, P1 + // = ori D0, D0, (BIT(15)) + // = andi D0, D0, ~(BIT(21)) + // = std D0, EX_OHA_AISS_IO_REG_0x10020014, P0 +#endif + + // Branch to sub_slw_runtime_scom() + FAPI_INF("Launching Host Runtime SCOM routine") + // - bsrd D1 + + // Prep P1 + // - setp1_mcreadand D0 + +#if 0 + // Clear regular wake-up and restore PSCOM fence in OHA + // These were established in p9_sbe_ex_scominit.S + // = ld D0, EX_OHA_AISS_IO_REG_0x10020014, P1 + // = andi D0, D0, ~(BIT(15)) + // = ori D0, D0, BIT(21) + // = std D0, EX_OHA_AISS_IO_REG_0x10020014, P0 + // Enable the AISS to allow further operation + // = ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + // = ori D0, D0, (BIT(1)) + // = std D0, EX_OHA_MODE_REG_RWx1002000D, P0 +#endif + + // - bra 2f + // - 1: + + // To accomodate IPL flow, where sub_slw_runtime_scom() is skipped + // - setp1_mcreadand D0 + +#if 0 + // Clear regular wake-up and restore PSCOM fence in OHA + // These were established in p9_sbe_ex_scominit.S + // = ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + // = andi D0, D0, ~BIT(1) + // = std D0, EX_OHA_MODE_REG_RWx1002000D, P0 + // = ld D0, EX_OHA_AISS_IO_REG_0x10020014, P1 + // = andi D0, D0, ~(BIT(15)) + // = ori D0, D0, BIT(21) + // = std D0, EX_OHA_AISS_IO_REG_0x10020014, P0 + // Enable the AISS to allow further operation + // = ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + // = ori D0, D0, (BIT(1)) + // = std D0, EX_OHA_MODE_REG_RWx1002000D, P0 +#endif + // - 2: + + // If using cv_multicast, we need to set the magic istep number here + // - la A0, p9_sbe_select_ex_control + // - ldandi D0, 0, A0, P9_CONTROL_INIT_ALL_EX + // - braz D0, 3f + FAPI_DBG("Setting istep num to magic number because cv_multicast is set") + // - lpcs P1, MBOX_SBEVITAL_0x0005001C + // - sti MBOX_SBEVITAL_0x0005001C, P1, (P9_SBE_EX_RAS_RUNTIME_SCOM_MAGIC_ISTEP_NUM << (4+32)) + // - 3: + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_ras_runtime_scom.H b/src/ppe/hwp/cache/p9_hcd_cache_ras_runtime_scom.H new file mode 100644 index 0000000..ec9a389 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_ras_runtime_scom.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_ras_runtime_scom.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_ras_runtime_scom.H +/// @brief EX FSP/Host runtime scoms +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + + +#ifndef __P9_HCD_CACHE_RAS_RUNTIME_SCOM_H__ +#define __P9_HCD_CACHE_RAS_RUNTIME_SCOM_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_ras_runtime_scom_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_ras_runtime_scom_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EX>&); + +/// @brief EX FSP/Host runtime scoms +/// +/// @param [in] i_target TARGET_TYPE_EX target +/// +/// @attr +/// @attritem ATTR_CACHE_RAS_SCOM_LOC - EX target, uint32 +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_ras_runtime_scom( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_RAS_RUNTIME_SCOM_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_repair_initf.C b/src/ppe/hwp/cache/p9_hcd_cache_repair_initf.C new file mode 100644 index 0000000..e986a81 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_repair_initf.C @@ -0,0 +1,87 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_repair_initf.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_repair_initf.C +/// @brief Load Repair ring for EX non-core +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Load cache ring images from MVPD +/// These rings must contain ALL chip customization data. +/// This includes the following: Repair Power headers, and DTS +/// Historically this was stored in MVPD keywords are #R, #G. Still stored in /// MVPD, but SBE image is customized with rings for booting cores +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_repair_initf.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Procedure: Load Repair ring for cache +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_repair_initf( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + // scan chiplet specific ring content + FAPI_DBG("Scanning EX REPAIR rings...") + // - load_ring_vec_ex ex_repr_eco + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_repair_initf.H b/src/ppe/hwp/cache/p9_hcd_cache_repair_initf.H new file mode 100644 index 0000000..ab8484f --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_repair_initf.H @@ -0,0 +1,64 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_repair_initf.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_repair_initf.H +/// @brief Load Repair ring for EX non-core +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_REPAIR_INITF_H__ +#define __P9_HCD_CACHE_REPAIR_INITF_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_repair_initf_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_repair_initf_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EX>&); + + +/// @brief Load Repair ring for EX non-core +/// +/// @param [in] i_target TARGET_TYPE_EX target +/// +/// @attr +/// @attritem ATTR_CACHE_REPAIR_RING - EX target, uint32 +/// pointer to RS4 content, VPD #R Keyword content(RS4)<br> +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_repair_initf( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_REPAIR_INITF_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_runinit.C b/src/ppe/hwp/cache/p9_hcd_cache_runinit.C new file mode 100644 index 0000000..eb6f5fe --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_runinit.C @@ -0,0 +1,73 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_runinit.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_runinit.C +/// @brief execute all cache init procedures +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_runinit.H" + +//------------------------------------------------------------------------------ +// Constant Definitions: +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Procedure: +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_runinit( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target) +{ + return fapi2::FAPI2_RC_SUCCESS; + +#if 0 + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; +#endif + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_runinit.H b/src/ppe/hwp/cache/p9_hcd_cache_runinit.H new file mode 100644 index 0000000..2b22d35 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_runinit.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_runinit.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_runinit.H +/// @brief execute all cache init procedures +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_RUNINIT_H__ +#define __P9_HCD_CACHE_RUNINIT_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_runinit_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_runinit_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&); + + +/// @brief execute all cache init procedures +/// +/// @param [in] i_target TARGET_TYPE_PROC_CHIP target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_runinit( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_RUNINIT_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_scomcust.C b/src/ppe/hwp/cache/p9_hcd_cache_scomcust.C new file mode 100644 index 0000000..789f954 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_scomcust.C @@ -0,0 +1,93 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_scomcust.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_scomcust.C +/// @brief Core Chiplet PCB Arbitration +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// If CME, request PCB Mux. +/// Poll for PCB Mux grant +/// Else (SBE) +/// Nop (as the CME is not running in bringing up the first Core) +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_scomcust.H" + +//------------------------------------------------------------------------------ +// Constant Definitions: Core Chiplet PCB Arbitration +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_scomcust( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target) +{ + +#if 0 + + fapi2::buffer<uint64_t> data; + + //Dynamically built (and installed) routine that is inserted by the .XIP + //Customization. process. (New for P9) + //(TODO: this part of the process is a placeholder at this point) + //Dynamically built pointer where a NULL is checked before execution + //If NULL (a potential early value); return + //Else call the function at the pointer; + //pointer is filled in by XIP Customization + //Customization items: + //Epsilon settings scan flush to super safe + //Customize Epsilon settings for system config + //LCO setup (chiplet specific) + //FW setups up based victim caches + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_scomcust.H b/src/ppe/hwp/cache/p9_hcd_cache_scomcust.H new file mode 100644 index 0000000..9837513 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_scomcust.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_scomcust.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_scomcust.H +/// @brief Core Chiplet PCB Arbitration +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_SCOMCUST_H__ +#define __P9_HCD_CACHE_SCOMCUST_H__ +extern "C" +{ + +/// @typedef p9_hcd_cache_scomcust_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_scomcust_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EX>&); + + +/// @brief Core Chiplet PCB Arbitration +/// +/// @param [in] i_target TARGET_TYPE_EX target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_scomcust( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_SCOMCUST_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_scominit.C b/src/ppe/hwp/cache/p9_hcd_cache_scominit.C new file mode 100644 index 0000000..869de65 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_scominit.C @@ -0,0 +1,130 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_scominit.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_scominit.C +/// @brief Cache Customization SCOMs +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Apply any SCOM initialization to the cache +/// Stop L3 configuration mode +/// Configure Trace Stop on Xstop +/// DTS Initialization sequense +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_scominit.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Procedure: Cache Customization SCOMs +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_scominit( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + /////// + // NCU + /////// + + /////// + // L3 + /////// + + FAPI_DBG("Configuring L3 disable"); + // - l3_setup L3_SETUP_ACTION_DISABLE, L3_SETUP_UNIT_L3 + + /////// + // OHA + /////// + + FAPI_DBG("Enable OHA to accept idle operations \ + by removing idle state override"); + // - setp1_mcreadand D1 + // = ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + FAPI_TRY(getScom(i_target, EX_OHA_MODE_REG_RWx1002000D, data)); + + //FAPI_DBG("Read OHA_MODE value: 0x%16llx", io_pore.d0.read()); + // = andi D0, D0, ~BIT(6) + data.clearBit<6>(); + + //FAPI_DBG("Updated OHA_MODE value: 0x%16llx", io_pore.d0.read()); + // = std D0, EX_OHA_MODE_REG_RWx1002000D, P0 + FAPI_TRY(putScom(i_target, EX_OHA_MODE_REG_RWx1002000D, data)); + + // set trace stop on checkstop + // Get the ECID to apply trace setup to only Murano DD2+ / Venice + // - lpcs P1, STBY_CHIPLET_0x00000000 + // - ldandi D0, PCBMS_DEVICE_ID_0x000F000F, P1, (CFAM_CHIP_ID_CHIP_MASK | CFAM_CHIP_ID_MAJOR_EC_MASK) + // - cmpibraeq D0, 1f, (CFAM_CHIP_ID_MURANO | CFAM_CHIP_ID_MAJOR_EC_1 ) + + FAPI_DBG("Configuring EX chiplet trace arrays \ + to stop on checkstop/recoverable errors") + // = sti GENERIC_DBG_MODE_REG_0x000107C0, P0, BIT(7) | BIT(8) + FAPI_TRY(putScom(i_target, GENERIC_DBG_MODE_REG_0x000107C0, + fapi2:buffer<uint64_t>().insertFromRight<7,2>(0x3))); + + // = sti GENERIC_DBG_TRACE_REG2_0x000107CB, P0, BIT(17) + FAPI_TRY(putScom(i_target, GENERIC_DBG_TRACE_REG2_0x000107CB, + fapi2:buffer<uint64_t>().setBit<17>())); + // - 1: + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_scominit.H b/src/ppe/hwp/cache/p9_hcd_cache_scominit.H new file mode 100644 index 0000000..0fd37c6 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_scominit.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_scominit.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_scominit.H +/// @brief Cache Customization SCOMs +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CACHE_SCOMINIT_H__ +#define __P9_HCD_CACHE_SCOMINIT_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_scominit_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_scominit_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EX>&); + + +/// @brief Cache Customization SCOMs +/// +/// @param [in] i_target TARGET_TYPE_EX target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_scominit( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_SCOMINIT_H__ diff --git a/src/ppe/hwp/cache/p9_hcd_cache_startclocks.C b/src/ppe/hwp/cache/p9_hcd_cache_startclocks.C new file mode 100644 index 0000000..3731f2e --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_startclocks.C @@ -0,0 +1,275 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_startclocks.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_startclocks.C +/// @brief Quad Clock Start +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Set (to be sure they are set under all conditions) core logical fences +/// (new for P9) +/// Drop pervasive thold +/// Setup L3 EDRAM/LCO +/// Drop pervasive fence +/// Reset abst clock muxsel, sync muxsel +/// Set fabric node/chip ID from the nest version +/// Clear clock controller scan register before start +/// Start arrays + nsl regions +/// Start sl + refresh clock regions +/// Check for clocks started +/// If not, error +/// Clear force align +/// Clear flush mode +/// Drop the chiplet fence to allow PowerBus traffic +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_cache_startclocks.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ + +#define STEP_EX_START_CLOCKS_NSL 0x1 +#define STEP_EX_START_CLOCKS_SL 0x2 +#define STEP_EX_START_CLOCKS_RUNNING 0x3 +#define STEP_EX_START_CLOCKS_SUCCESS 0x4 + + +//------------------------------------------------------------------------------ +// Procedure: Quad Clock Start +//------------------------------------------------------------------------------ + + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_cache_startclocks( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + FAPI_INF("<p9_hcd_cache_startclocks>: \ + P8 Start EX-Clocks started"); + + // Drop the Pervasive THOLD + // PM Exit States: WINKLE_EXIT_DROP_PERV_THOLD + // = sti EX_PMGP0_AND_0x100F0101,P0, ~(BIT(4)) + FAPI_TRY(putScom(i_target, EX_PMGP0_AND_0x100F0101, + fapi2:buffer<uint64_t>().flush<1>().clearBit<4>())); + + FAPI_DBG("Enabling L3 EDRAM/LCO setup"); + // - l3_setup L3_SETUP_ACTION_ENABLE, L3_SETUP_UNIT_L3_EDRAM + + // Drop perv fence GP0.63 multicast scomreg write + // = sti GENERIC_GP0_AND_0x00000004, P0, ~BIT(63) + FAPI_TRY(putScom(i_target, GENERIC_GP0_AND_0x00000004, + fapi2:buffer<uint64_t>().flush<1>().clearBit<63>())); + + // Reset abstclk_muxsel, synclk_muxsel (io_clk_sel) + // = sti GENERIC_GP0_AND_0x00000004, P0, ~BITS(0,2) + FAPI_TRY(putScom(i_target, GENERIC_GP0_AND_0x00000004, + fapi2:buffer<uint64_t>().flush<1>().insertFromRight<0,2>(0x0))); + + // Set ABIST_MODE_DC for core chiplets (core recovery) + // = sti GENERIC_GP0_OR_0x00000005, P0, BIT(11)|BIT(13) + FAPI_TRY(putScom(i_target, GENERIC_GP0_OR_0x00000005, + fapi2:buffer<uint64_t>().setBit<11>().setBit<13>())); + + // set fabric node/chip ID values (read from nest chiplet) + // read from nest chiplet + // - lpcs P1, NEST_CHIPLET_0x02000000 + // - ldandi D0, NEST_GP0_0x02000000, P1, BITS(40, 6) + // = std D0, GENERIC_GP0_OR_0x00000005, P0 + //FAPI_TRY(putScom(i_target, GENERIC_GP0_OR_0x00000005, data)); + + // Write ClockControl, Scan Region Register, + // set all bits to zero prior clock start + // = sti GENERIC_CLK_SCANSEL_0x00030007, P0, 0x0000000000000000 + FAPI_TRY(putScom(i_target, GENERIC_CLK_SCANSEL_0x00030007, 0x0)); + + // Write ClockControl, Clock Region Register, Clock Start command + // (arrays + nsl only, not refresh clock region) EX Chiplet + // = sti GENERIC_CLK_REGION_0x00030006, P0, 0x4FF0060000000000 + FAPI_TRY(putScom(i_target, GENERIC_CLK_REGION_0x00030006, + fapi2:buffer<uint64_t>(0x4FF0060000000000))); + // - updatestep STEP_EX_START_CLOCKS_NSL, D0, P1 + + // Write ClockControl, Clock Region Register, Clock Start command + // (sl + refresh clock region) EX Chiplet + // = sti GENERIC_CLK_REGION_0x00030006, P0, 0x4FF00E0000000000 + FAPI_TRY(putScom(i_target, GENERIC_CLK_REGION_0x00030006, + fapi2:buffer<uint64_t>(0x4FF00E0000000000))); + // - updatestep STEP_EX_START_CLOCKS_SL, D0, P1 + + // Read Clock Status Register (EX chiplet) + // check for bits 27:29 eq. zero, no tholds on + // 27 ROX CLOCK_STATUS_DPLL_FUNC_SL status of dpll_func_sl_thold + // 28 ROX CLOCK_STATUS_DPLL_FUNC_NSL status of dpll_func_nsl_thold + // output not used + // 29 ROX CLOCK_STATUS_DPLL_ARY_NSL status of dpll_ary_nsl_thold + // output not used + + // Needed to resolve SLW reading using a multicast group + // Get P1 setup for the chiplets to be targeted. + // - setp1_mcreadand D0 + + // = ld D0, GENERIC_CLK_STATUS_0x00030008, P1 + FAPI_TRY(getScom(i_target, GENERIC_CLK_STATUS_0x00030008, data)); + // - xori D0, D0, 0x00000003FFFFFFFF + // - branz D0, error_clock_start + + FAPI_DBG("<p9_hcd_cache_startclocks>: \ + EX clock running now"); + // - updatestep STEP_EX_START_CLOCKS_RUNNING, D0, P1 + + // Read the Global Checkstop FIR of dedicated EX chiplet + // - setp1_mcreador D0 + // = ld D0, GENERIC_XSTOP_0x00040000, P1 + FAPI_TRY(getScom(i_target, GENERIC_XSTOP_0x00040000, data)); + // - branz D0, error_checkstop_fir + + FAPI_DBG("<p9_hcd_cache_startclocks>: \ + All checkstop FIRs on initialized EX are zero"); + + // Clear force_align in all Chiplet GP0 + // = sti GENERIC_GP0_AND_0x00000004, P0, ~BIT(3) + FAPI_TRY(putScom(i_target, GENERIC_GP0_AND_0x00000004, + fapi2:buffer<uint64_t>().flush<1>().clearBit<3>())); + + // Clear flushmode_inhibit in Chiplet GP0 + // Can't do this on Murano & Venice DD1.x due to a logic bug in L3 HW250462 + // - lpcs P1, PCBMS_DEVICE_ID_0x000F000F + // - ldandi D0, PCBMS_DEVICE_ID_0x000F000F, P1, CFAM_CHIP_ID_MAJOR_EC_MASK + // - cmpibraeq D0, 1f, CFAM_CHIP_ID_MAJOR_EC_1 + // = sti GENERIC_GP0_AND_0x00000004, P0, ~BIT(2) + FAPI_TRY(putScom(i_target, GENERIC_GP0_AND_0x00000004, + fapi2:buffer<uint64_t>().flush<1>().clearBit<2>())); + // - 1: + + // Clear core2cache and cache2core fences. Necessary for Sleep, + // redundant (already clear) but not harmful for IPL/Winkle + // = sti EX_PMGP0_AND_0x100F0101,P0,~(BIT(20)|BIT(21)) + FAPI_TRY(putScom(i_target, EX_PMGP0_AND_0x100F0101, + fapi2:buffer<uint64_t>().flush<1>().insertFromRight<20,2>(0x0))); + + // Disable PM and DPLL override + FAPI_INF("<p9_hcd_cache_startclocks>: \ + Disable PM and DPLL override"); + // = sti EX_PMGP0_AND_0x100F0101,P0,~(BIT(0)|BIT(3)) + FAPI_TRY(putScom(i_target, EX_PMGP0_AND_0x100F0101, + fapi2:buffer<uint64_t>().flush<1>().insertFromRight<0,4>(0x6))); + + // PM Exit States: WINKLE_EXIT_WAIT_ON_OHA + // Drop fence GP3.18 to unfence the chiplet + // CMO-20130516: First clear the pbus purge request bit(14) from AISS + // - setp1_mcreador D0 + // = ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + // = andi D0, D0, ~BIT(1) + // = std D0, EX_OHA_MODE_REG_RWx1002000D, P0 + FAPI_TRY(getScom(i_target, EX_OHA_MODE_REG_RWx1002000D, data)); + data.clearBit<1>(); + FAPI_TRY(putScom(i_target, EX_OHA_MODE_REG_RWx1002000D, data)); + // = ld D0, EX_OHA_AISS_IO_REG_0x10020014, P1 + // = andi D0, D0, ~BIT(14) + // = std D0, EX_OHA_AISS_IO_REG_0x10020014, P0 + FAPI_TRY(getScom(i_target, EX_OHA_AISS_IO_REG_0x10020014, data)); + data.clearBit<14>(); + FAPI_TRY(putScom(i_target, EX_OHA_AISS_IO_REG_0x10020014, data)); + // = ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + // = ori D0, D0, BIT(1) + // = std D0, EX_OHA_MODE_REG_RWx1002000D, P0 + FAPI_TRY(getScom(i_target, EX_OHA_MODE_REG_RWx1002000D, data)); + data.setBit<1>(); + FAPI_TRY(putScom(i_target, EX_OHA_MODE_REG_RWx1002000D, data)); + // Now drop pb fence bit(18) + // = sti GENERIC_GP3_AND_0x000F0013,P0, ~BIT(18) + FAPI_TRY(putScom(i_target, GENERIC_GP3_AND_0x000F0013, + fapi2:buffer<uint64_t>().flush<1>().clearBit<18>())); + + // Drop fence GP3.26 to allow PCB operations to the chiplet + // = sti GENERIC_GP3_AND_0x000F0013,P0, ~BIT(26) + FAPI_TRY(putScom(i_target, GENERIC_GP3_AND_0x000F0013, + fapi2:buffer<uint64_t>().flush<1>().clearBit<26>())); + // - updatestep STEP_EX_START_CLOCKS_SUCCESS, D0, P1 + FAPI_INF("<p9_hcd_cache_startclocks>: \ + Exiting procedure successfully"); + + // - ifidle D0, 1f + //Not idle Check secure mode + // - ifbitclrscom D1, D1, OTPC_M_SECURITY_SWITCH_0x00010005, P1, 1, 1f + //Trusted boot is set, set core trusted boot. + // = sti EX_TRUSTED_BOOT_EN_0x10013C03, P0, BIT(0) + FAPI_TRY(putScom(i_target, GENERIC_GP3_AND_0x000F0013, + fapi2:buffer<uint64_t>().flush<1>().clearBit<0>())); + // - 1: + +//------------------------------------------------------------------------------ +// ERROR -- Clocks failed to start +//------------------------------------------------------------------------------ +error_clock_start: + FAPI_ERR("<p9_hcd_cache_startclocks>: \ + Clock Start Error on EX detected"); + // - reqhalt RC_SBE_EX_STARTCLOCKS_CLOCKS_NOT_STARTED + +//------------------------------------------------------------------------------ +// ERROR -- Checkstop detected +//------------------------------------------------------------------------------ +error_checkstop_fir: + FAPI_ERR("<p9_hcd_cache_startclocks>: \ + Checkstop FIR on initialized EX is not zero, \ + VITAL register was updated"); + // - reqhalt RC_SBE_EX_STARTCLOCKS_CHIP_XSTOPPED + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + + + diff --git a/src/ppe/hwp/cache/p9_hcd_cache_startclocks.H b/src/ppe/hwp/cache/p9_hcd_cache_startclocks.H new file mode 100644 index 0000000..a6aa1d6 --- /dev/null +++ b/src/ppe/hwp/cache/p9_hcd_cache_startclocks.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/cache/p9_hcd_cache_startclocks.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_cache_startclocks.H +/// @brief Quad Clock Start +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Sangeetha T S <sangeet2@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + + +#ifndef __P9_HCD_CACHE_STARTCLOCKS_H__ +#define __P9_HCD_CACHE_STARTCLOCKS_H__ + +extern "C" +{ + +/// @typedef p9_hcd_cache_startclocks_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_cache_startclocks_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EX>&); + +/// @brief Quad Clock Start +/// +/// @param [in] i_target TARGET_TYPE_EX target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_cache_startclocks( + const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target); + + +} // extern C + +#endif // __P9_HCD_CACHE_STARTCLOCKS_H__ diff --git a/src/ppe/hwp/core/Makefile b/src/ppe/hwp/core/Makefile new file mode 100644 index 0000000..9842d1f --- /dev/null +++ b/src/ppe/hwp/core/Makefile @@ -0,0 +1,54 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/hwp/core/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 + +# This Makefile compiles all of the core hardware procedure code. See the +# "corehcdfiles.mk" file in this directory. + +#all generated files from this makefile will end up in obj/cache +export SUB_OBJDIR = /core + +include img_defs.mk +include corehcdfiles.mk + + +OBJS := $(addprefix $(OBJDIR)/, $(CACHE_OBJECTS)) + +libcore.a: core + $(AR) crs $(OBJDIR)/libcore.a $(OBJDIR)/*.o + +.PHONY: clean core +core: $(OBJS) + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +clean: + rm -fr $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/hwp/core/corehcdfiles.mk b/src/ppe/hwp/core/corehcdfiles.mk new file mode 100644 index 0000000..364de0c --- /dev/null +++ b/src/ppe/hwp/core/corehcdfiles.mk @@ -0,0 +1,65 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/hwp/core/corehcdfiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file corehcdfiles.mk +# +# @brief mk for including core hcode object files +# +# @page ChangeLogs Change Logs +# @section corehcdfiles.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# Object Files +########################################################################## + +CACHE-CPP-SOURCES += p9_hcd_core_arrayinit.C +CACHE-CPP-SOURCES += p9_hcd_core_chiplet_init.C +CACHE-CPP-SOURCES += p9_hcd_core_chiplet_reset.C +CACHE-CPP-SOURCES += p9_hcd_core_gptr_time_initf.C +CACHE-CPP-SOURCES += p9_hcd_core_initf.C +CACHE-CPP-SOURCES += p9_hcd_core_occ_runtime_scom.C +CACHE-CPP-SOURCES += p9_hcd_core_pcb_arb.C +CACHE-CPP-SOURCES += p9_hcd_core_poweron.C +CACHE-CPP-SOURCES += p9_hcd_core_ras_runtime_scom.C +CACHE-CPP-SOURCES += p9_hcd_core_repair_initf.C +CACHE-CPP-SOURCES += p9_hcd_core_runinit.C +CACHE-CPP-SOURCES += p9_hcd_core_scomcust.C +CACHE-CPP-SOURCES += p9_hcd_core_scominit.C +CACHE-CPP-SOURCES += p9_hcd_core_startclocks.C + +CACHE-C-SOURCES += +CACHE-S-SOURCES += + +CACHE_OBJECTS += $(CACHE-CPP-SOURCES:.C=.o) +CACHE_OBJECTS += $(CACHE-C-SOURCES:.c=.o) +CACHE_OBJECTS += $(CACHE-S-SOURCES:.S=.o) + diff --git a/src/ppe/hwp/core/p9_hcd_core.H b/src/ppe/hwp/core/p9_hcd_core.H new file mode 100644 index 0000000..a96280f --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core.H @@ -0,0 +1,54 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core.H +/// @brief Core Chiplet Procedure Includes +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CORE_H__ +#define __P9_HCD_CORE_H__ + +#include <p9_hcd_core_arrayinit.H> +#include <p9_hcd_core_chiplet_init.H> +#include <p9_hcd_core_chiplet_reset.H> +#include <p9_hcd_core_gptr_time_initf.H> +#include <p9_hcd_core_initf.H> +#include <p9_hcd_core_occ_runtime_scom.H> +#include <p9_hcd_core_pcb_arb.H> +#include <p9_hcd_core_poweron.H> +#include <p9_hcd_core_ras_runtime_scom.H> +#include <p9_hcd_core_repair_initf.H> +#include <p9_hcd_core_runinit.H> +#include <p9_hcd_core_scomcust.H> +#include <p9_hcd_core_scominit.H> +#include <p9_hcd_core_startclocks.H> + +#endif // __P9_HCD_CORE_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_arrayinit.C b/src/ppe/hwp/core/p9_hcd_core_arrayinit.C new file mode 100644 index 0000000..58c6ecc --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_arrayinit.C @@ -0,0 +1,156 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_arrayinit.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_arrayinit.C +/// @brief Core Initialize arrays +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Use ABIST engine to zero out all arrays +/// Upon completion, scan0 flush all rings except Vital,Repair,GPTR,and TIME +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_arrayinit.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Procedure: Core Initialize arrays +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_arrayinit( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) + +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + // Procedure Prereq : P0 is pointing to the targeted EX chiplet + // submodules: + // seeprom_array_init_module + // ex_scan0 + + FAPI_INF("<p9_hcd_core_arrayinit> : \ + *** Array Init and Scan0 Cleanup for EX Chiplets ***"); + + // SBE Address Base Register Setups + // Setup PRV_BASE_ADDR1; points to selected EX chiplet + // - mr P1, P0 + FAPI_INF("<p9_hcd_core_arrayinit> : \ + Copy selected EX info from P0 to P1"); + + // Step 1: Array Init for selected EX chiplet + // ARRAY INIT module -> see p9_sbe_tp_array_init.S + // + // At entry: + // + // P1 : The chiplet ID/Multicast Group + // D1 : Clock Regions for Array Init + // + // At exit: + // + // P0, D0, D1, CTR : destroyed + // P1, A0, A1 : maintained + // + FAPI_INF("<p9_hcd_core_arrayinit> : \ + Calling Array Init Subroutine"); + + // >>> Sleep + // - li D1, SCAN_CLK_CORE_ONLY + + // Execute the array init + // - bsr seeprom_array_init_module + + // Restore P0 with selected EX chiplet info + // - mr P0, P1 + FAPI_INF("<p9_hcd_core_arrayinit> : \ + Copy selected EX info back from P1 to P0"); + + // Step 2: Scan0 for selected EX chiplet except PRV, GPTR, TIME and DPLL + FAPI_INF("<p9_hcd_core_arrayinit> : \ + Calling Scan0 Subroutine"); + + // taken from p9_sbe_ex_chiplet_init + + // >>> Sleep scan flush - core only + + // Hook to bypass in Sim + // - hooki 0, 0xFF04 + // - ifslwcntlbitset P9_SLW_SKIP_FLUSH,2f + + FAPI_DBG("EX ArrayInit: Scan0 Module executed: \ + Scan all core chains except GPTR and TIME"); + + // Each scan0 will rotate the ring 8191 latches (2**13 - 1) and the + // the longest ring is defined by P9_SCAN0_FUNC_REPEAT. When the design + // ALWAYS has all stumps less than 8191, the repeat (eg .rept) can be + // removed. + // Implementation note: this is not done in a loop (or included in the + // ex_scan0_module itself) as the D0 and D1 registers are used in + // ex_scan0_module and there is no convenient place to temporaily store + // the 2-64b values values. Argueably, PIBMEM could be used for this + // but was not utilized. + + // - .rept P9_SCAN0_FUNC_REPEAT + // - ex_scan0 SCAN_CORE_ALL_BUT_GPTRTIMEREP, SCAN_CLK_CORE_ONLY + // - .endr + // - 2: + + FAPI_INF("<p9_hcd_core_arrayinit> : \ + *** End of Procedure ***"); + + return fapi2::FAPI2_RC_SUCCESS; + +clean_up: + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/core/p9_hcd_core_arrayinit.H b/src/ppe/hwp/core/p9_hcd_core_arrayinit.H new file mode 100644 index 0000000..b0eeb5e --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_arrayinit.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_arrayinit.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_arrayinit.H +/// @brief Core Initialize arrays +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + + +#ifndef __P9_HCD_CORE_ARRAYINIT_H__ +#define __P9_HCD_CORE_ARRAYINIT_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_arrayinit_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_arrayinit_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + +/// @brief Core Initialize arrays +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_arrayinit( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_ARRAYINIT_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_chiplet_init.C b/src/ppe/hwp/core/p9_hcd_core_chiplet_init.C new file mode 100644 index 0000000..3d3763a --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_chiplet_init.C @@ -0,0 +1,136 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_chiplet_init.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_chiplet_init.C +/// @brief Core Flush/Initialize +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Switch the core glitchless mux to allow DPLL clocks on the clock grid +/// Scan0 flush all chiplet rings except VITAL, GPTR and TIME +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_chiplet_init.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ +//#define SIM_PLL +//#define SIM_SPEEDUP +////#define SCAN0_DISABLE +//#define STEP_CHIPLET_INIT_0 0x0 // Resetting DPLL +//#define STEP_CHIPLET_INIT_1 0x1 // Core+ECO glmux switch (IPL/Winkle) +//#define STEP_CHIPLET_INIT_2 0x2 // Core glmux switch (Sleep) +//#define STEP_CHIPLET_INIT_3 0x3 // Before Func flush for IPL/Winkle +//#define STEP_CHIPLET_INIT_4 0x4 // After Func flush for IPL/Winkle +//#define STEP_CHIPLET_INIT_5 0x5 // After Func flush for IPL/Winkle +//#define STEP_CHIPLET_INIT_6 0x6 // Before Core GPTR flush for Sleep +//#define STEP_CHIPLET_INIT_7 0x7 // After Core GPTR flush for Sleep +//#define STEP_CHIPLET_INIT_8 0x8 // Before Core Func flush for Sleep +//#define STEP_CHIPLET_INIT_9 0x9 // After Core Func flush for Sleep +//#define STEP_CHIPLET_INIT_A 0xA // Before Core Func flush for Sleep +//#define STEP_CHIPLET_INIT_B 0xB // After Core Func flush for Sleep +//#define PORE_REFCLK_CYCLES 1 // \todo need real value for hdw +//#define DPLL_LOCK_DELAY 8192*PORE_REFCLK_CYCLES + +//------------------------------------------------------------------------------ +// Procedure: Core Flush/Initialize +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_chiplet_init( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) +{ + +#if 0 + + fapi2::buffer<uint64_t> data; + + // Procedure Prereq: + // p9_sbe_ex_chiplet_reset, p9_sbe_ex_dpll_initf, p9_sbe_ex_pll_initf + + FAPI_INF("<p9_hcd_cache_chiplet_init>: Entering procedure"); + + // Look for PSCOM error on any chip, fail if we find one + // scan0 flush all configured chiplet rings except EX DPLL + // call ex_scan0_module( ) + + // >>> Sleep GPTR flush - core only + // This is done after the swing of the Glitchless Mux above + // Hook to bypass in sim while providing a trace + + // Hook to bypass in sim while providing a trace + // - hooki 0, 0xFF04 + // - ifslwcntlbitset P9_SLW_SKIP_FLUSH,1f + + FAPI_DBG("EX Reset: Scan0 Module executed for Sleep: \ + Scan the all but GPTR/TIME/REP rings"); + + // Each scan0 will rotate the ring 8191 latches (2**13 - 1) and the + // the longest ring is defined by P9_SCAN0_FUNC_REPEAT. When the design + // ALWAYS has all stumps less than 8191, the repeat (eg .rept) can be + // removed. + // Implementation note: this is not done in a loop (or included in the + // ex_scan0_module itself) as the D0 and D1 registers are used in + // ex_scan0_module and there is no convenient place to temporaily store + // the 2-64b values values. Argueably, PIBMEM could be used for this + // but was not utilized. + // - updatestep STEP_CHIPLET_INIT_A, D0, P1 + // - .rept P9_SCAN0_FUNC_REPEAT + // - ex_scan0 SCAN_CORE_ALL_BUT_GPTRTIMEREP, SCAN_CLK_CORE_ONLY + // - .endr + // - updatestep STEP_CHIPLET_INIT_B, D0, P1 + // - 1: + + FAPI_INF("<p9_hcd_cache_chiplet_init>: Exiting procedure"); + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + diff --git a/src/ppe/hwp/core/p9_hcd_core_chiplet_init.H b/src/ppe/hwp/core/p9_hcd_core_chiplet_init.H new file mode 100644 index 0000000..be081ef --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_chiplet_init.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_chiplet_init.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_chiplet_init.H +/// @brief Core Flush/Initialize +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CORE_CHIPLET_INIT_H__ +#define __P9_HCD_CORE_CHIPLET_INIT_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_chiplet_init_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_chiplet_init_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + + +/// @brief Core Flush/Initialize +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_chiplet_init( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_CHIPLET_INIT_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_chiplet_reset.C b/src/ppe/hwp/core/p9_hcd_core_chiplet_reset.C new file mode 100644 index 0000000..1874f0f --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_chiplet_reset.C @@ -0,0 +1,196 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_chiplet_reset.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_chiplet_reset.C +/// @brief Core Chiplet Reset +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Reset chiplet logic +/// (TODO: check with Andreas on the effect of a CME based Endpoint reset +/// relative to the CorePPM path) +/// Scan0 flush entire core chiplet +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_chiplet_reset.H" + +//------------------------------------------------------------------------------ +// Constant Definitions +//------------------------------------------------------------------------------ + +// GP3 Bits +// 1 - PCB_EP_RESET +// 2 - GLMMUX Reset +// 3 - PLL_TEST Enable +// 4 - PLLRST - PLL Reset +// 5 - PLL Bypass +// 11 - D_MODE for Vital +// 13 - MPW2 for Vital +// 14 - PMW1 for Vital +// 18 - FENCE_EN for chiplet +// 22 - Resonant Clock disable +// 23:24 - Glitchless Mux Sel +// 25: - ?? (set because System Pervasive flow does this) +// Background: system pervasive as the following setting in their tests: +// 7C1623C000000000 +// Bits set: +// 1, 2, 3, 4, 5, 11, 13, 14, 18, 22, 23, 24, 25 +//#define GP3_INIT_VECTOR (BITS(1,5)|BIT(11)|BIT(13)|BIT(14)|BIT(18)|BIT(22)|BIT(23)|BIT(24)|BIT(25)) + +// hang counter inits +//#define HANG_P1_INIT 0x0400000000000000 +//#define PCB_SL_ERROR_REG_RESET 0xFFFFFFFFFFFFFFFF +//#define STEP_CHIPLET_RESET_1 0x1 // After start of vital clocks +//#define STEP_CHIPLET_RESET_2 0x2 // After fence drop +//#define STEP_CHIPLET_RESET_3 0x3 // Before GPTR flush for IPL/Winkle +//#define STEP_CHIPLET_RESET_4 0x4 // After GPTR flush for IPL/Winkle +//#define STEP_CHIPLET_RESET_5 0x5 // Before Func flush for IPL/Winkle +//#define STEP_CHIPLET_RESET_6 0x6 // After Func flush for IPL/Winkle +//#define STEP_CHIPLET_RESET_7 0x7 // Before GPTR flush for Sleep +//#define STEP_CHIPLET_RESET_8 0x8 // After GPTR flush for Sleep + +//------------------------------------------------------------------------------ +// Procedure: Core Chiplet Reset +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_chiplet_reset( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + ///////////////////////////////////////////////////////////////// + // repeat some init steps of chiplet_init + ///////////////////////////////////////////////////////////////// + + // If there is a unused, powered-off EX chiplet which needs to be + // configured in the following steps to setup the PCB endpoint. + + // Skip the PCB endpoint config steps for sleep so that fences don't + // get dropped (eg by dropping chiplet_enable (GP3(0)). + + // The following is performed for both IPL/Winkle and Sleep + + // Note: These are executed for sleep as well as these fences will have + // already been dropped + + FAPI_DBG("<p9_hcd_core_chiplet_reset>: \ + Remove pervasive ECO fence;"); + // ECO Fence in 22 + // = sti EX_PMGP0_AND_0x100F0101,P0,~(BIT(22)) + FAPI_TRY(putScom(i_target, EX_PMGP0_AND_0x100F0101, + fapi2:buffer<uint64_t>().flush<1>().clearBit<22>())); + + FAPI_DBG("<p9_hcd_core_chiplet_reset>: \ + Remove winkle mode before scan0 on EX chiplets is executed"); + // PM Exit States: WINKLE_EXIT_DROP_ELEC_FENCE + + FAPI_DBG("<p9_hcd_core_chiplet_reset>: \ + Remove logical pervasive/pcbs-pm fence"); + // = sti EX_PMGP0_AND_0x100F0101,P0,~(BIT(39)) + FAPI_TRY(putScom(i_target, EX_PMGP0_AND_0x100F0101, + fapi2:buffer<uint64_t>().flush<1>().clearBit<39>())); + + FAPI_DBG("<p9_hcd_core_chiplet_reset>: \ + Remove PB Winkle Electrical Fence GP3(27)"); + // = sti EX_GP3_AND_0x100F0013,P0,~(BIT(27)) + FAPI_TRY(putScom(i_target, EX_GP3_AND_0x100F0013, + fapi2:buffer<uint64_t>().flush<1>().clearBit<27>())); + + FAPI_DBG("<p9_hcd_core_chiplet_reset>: \ + Configuring chiplet hang counters") ; + // = sti EX_HANG_P1_0x100F0021,P0,HANG_P1_INIT + FAPI_TRY(putScom(i_target, EX_HANG_P1_0x100F0021, HANG_P1_INIT)); + // - updatestep STEP_CHIPLET_RESET_2, D0, P1 + + ////////////////////////////////////////////////////////////// + // perform scan0 module for pervasive chiplet (GPTR_TIME_REPR) + ////////////////////////////////////////////////////////////// + + // For the Sleep case, the DPLL is running but the core mesh is force to + // the "constant" or "off" state. In order to flush or scan, the mesh must + // be reenabled via the Glitchless Mux. + + // Read-modify-write (vs sti AND and sti OR) is done so that glitchless + // mux change field change is atomic (eg 1 store) + // - setp1_mcreadand D1 + // = ld D1,EX_PMGP0_0x100F0100,P1 + FAPI_TRY(fapi2::getScom(i_target, EX_PMGP0_0x100F0100, data)); + + // Set the core glitchless mux to use the primary input (b00). + // Upon Sleep entry, hardware will switch the glitchless mux to 0b10 + // (constant). EX PM GP0 bits 32-33) + FAPI_INF("EX Chiplet -> Set glitchless mux select for core domain to 00 ") + // = andi D1, D1, ~(BIT(32)|BIT(33)) + + // Store the final result to the hardware + // = std D1,EX_PMGP0_0x100F0100,P0 + data.insertFromRight<32,2>(0x0); + FAPI_TRY(putScom(i_target, EX_PMGP0_0x100F0100, data)); + // - updatestep STEP_CHIPLET_RESET_7, D0, P1 + + // Hook to bypass in sim while providing a trace + // - hooki 0, 0xFF03 + // - ifslwcntlbitset P9_SLW_SKIP_FLUSH,1f + + FAPI_DBG("EX Reset: Scan0 Module executed for Sleep: \ + Scan the GPTR/TIME/REP rings"); + + // - .rept P9_SCAN0_GPTR_REPEAT + // - ex_scan0 SCAN_CORE_GPTR_TIME_REP, SCAN_CLK_CORE_ONLY + // - .endr + // - 1: + // - updatestep STEP_CHIPLET_RESET_8, D0, P1 + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + diff --git a/src/ppe/hwp/core/p9_hcd_core_chiplet_reset.H b/src/ppe/hwp/core/p9_hcd_core_chiplet_reset.H new file mode 100644 index 0000000..6d95c93 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_chiplet_reset.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_chiplet_reset.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_chiplet_reset.H +/// @brief Core Chiplet Reset +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CORE_CHIPLET_RESET_H__ +#define __P9_HCD_CORE_CHIPLET_RESET_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_chiplet_reset_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_chiplet_reset_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + + +/// @brief Core Chiplet Reset +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_chiplet_reset( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_CHIPLET_RESET_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_gptr_time_initf.C b/src/ppe/hwp/core/p9_hcd_core_gptr_time_initf.C new file mode 100644 index 0000000..e6b54ed --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_gptr_time_initf.C @@ -0,0 +1,112 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_gptr_time_initf.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_gptr_time_initf.C +/// @brief Load Core GPTR and Time rings +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// initfiles in procedure defined on VBU ENGD wiki (TODO add link) +/// to produce #G VPD contents +/// Check for the presence of core override GPTR ring from image +/// (this is new for P9) +/// if found, apply; if not, apply core GPTR from image +/// Check for the presence of core override TIME ring from image; +/// if found, apply; if not, apply core base TIME from image +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_gptr_time_initf.H" + +//----------------------------------------------------------------------------- +// Constant Definitions +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Procedure: Load Core GPTR and Time rings +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_gptr_time_initf( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) +{ + +#if 0 + + // >>> For sleep, bypass the pull back of the scan ratio + // - ifsleep D0, 1f + // Set EX scan ratio to 1:1 as EX is still at refclock + FAPI_INF("<p9_hcd_core_gptr_time_initf> : \ + Set EX scan ratio to 1:1 ...") + // = sti EX_OPCG_CNTL0_0x10030002, P0, 0x0 + FAPI_TRY(fapi2::putScom(i_target, EX_OPCG_CNTL0_0x10030002, 0x0)); + // - 1: + + // scan ring content shared among all chiplets + FAPI_DBG("Scanning EX core GPTR rings...") + // - load_ring ex_gptr_core skipoverride=1 + // - load_ring ex_gptr_l2 skipoverride=1 + + // scan chiplet specific ring content + FAPI_DBG("Scanning EX core TIME rings...") + // - load_ring_vec_ex ex_time_core + + // Set EX scan ratio back to 8:1 + FAPI_INF("<p9_hcd_core_gptr_time_initf> : \ + Set EX scan ratio to 8:1 ...") + //Inputs: A1 and P0 and D0, destroys D0 & D1 + // - .pibmem_port (PORE_SPACE_PIBMEM & 0xf) + // - lpcs P1, PIBMEM0_0x00080000 + // - ld D0, ex_scan_ratio_override, P1 + // - bsr set_scan_ratio_d0 + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/core/p9_hcd_core_gptr_time_initf.H b/src/ppe/hwp/core/p9_hcd_core_gptr_time_initf.H new file mode 100644 index 0000000..881f493 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_gptr_time_initf.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_gptr_time_initf.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_gptr_time_initf.H +/// @brief Load Core GPTR and Time rings +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CORE_GPTR_TIME_INIT_H__ +#define __P9_HCD_CORE_GPTR_TIME_INIT_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_gptr_time_initf_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_gptr_time_initf_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + +/// @brief Load Core GPTR and Time rings +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// @attr +/// @attritem ATTR_CORE_GPTR_TIME_RING - EC target, uint32 +/// pointer to RS4 content<br> +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_gptr_time_initf( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_GPTR_TIME_INIT_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_initf.C b/src/ppe/hwp/core/p9_hcd_core_initf.C new file mode 100644 index 0000000..fad2046 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_initf.C @@ -0,0 +1,95 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_initf.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_initf.C +/// @brief Core scan init +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Initfiles in procedure defined on VBU ENGD wiki (TODO add link) +/// Check for the presence of core FUNC override rings from image; +/// if found, apply; if not, apply core base FUNC rings from image +/// Note: FASTINIT ring (eg CMSK ring) is setup at this point to limit the +/// stumps that participate in FUNC ring scanning (this is new for P9). +/// (TODO to make sure the image build support is in place) +/// Note : if in fused mode, both core rings will be initialized to the same +/// values via multicast scans +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_initf.H" + +//----------------------------------------------------------------------------- +// Constant Definitions +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Procedure: Core scan init +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_initf( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) +{ + +#if 0 + + fapi2::buffer<uint64_t> data; + + // - load_ring ex_func_core conditional_override=1 + // - load_ring ex_regf_core conditional_override=1 + // - load_ring ex_fary_l2 conditional_override=1 + // - load_ring ex_lbst_core conditional_override=1 + // - load_ring ex_abfa_core conditional_override=1 + // - load_ring ex_cmsk_core conditional_override=1 + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/core/p9_hcd_core_initf.H b/src/ppe/hwp/core/p9_hcd_core_initf.H new file mode 100644 index 0000000..7a9682d --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_initf.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_initf.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_initf.H +/// @brief Core scan init +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CORE_INITF_H__ +#define __P9_HCD_CORE_INITF_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_initf_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_initf_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + + +/// @brief Core scan init +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// @attr +/// @attritem ATTR_CORE_FUNC_RING - EC target, uint32 +/// pointer to RS4 content<br> +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_initf( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_INITF_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_occ_runtime_scom.C b/src/ppe/hwp/core/p9_hcd_core_occ_runtime_scom.C new file mode 100644 index 0000000..ccc4c0e --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_occ_runtime_scom.C @@ -0,0 +1,94 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_occ_runtime_scom.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_occ_runtime_scom.C +/// @brief Core OCC runtime SCOMS +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Run-time updates from OCC code that are put somewhere TBD +/// (TODO . revisit with OCC FW team) +/// OCC FW sets up value in the TBD SCOM section +/// This was not leverage in P8 with the demise of CPMs +/// Placeholder at this point +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_occ_runtime_scom.H" + +//----------------------------------------------------------------------------- +// Constant Definitions +//----------------------------------------------------------------------------- +#define host_runtime_scom 0 + +//----------------------------------------------------------------------------- +// Procedure: Core OCC runtime SCOMS +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_occ_runtime_scom( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) +{ + +#if 0 + + fapi2::buffer<uint64_t> data; + + // Run the SCOM sequence if the SCOM procedure is defined + // - la A0, occ_runtime_scom + // - ld D0, 0, A0 + // - braz D0, 1f + //FAPI_INF("Launching OCC Runtime SCOM routine") + // - bsrd D0 + // - 1: + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/core/p9_hcd_core_occ_runtime_scom.H b/src/ppe/hwp/core/p9_hcd_core_occ_runtime_scom.H new file mode 100644 index 0000000..0221370 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_occ_runtime_scom.H @@ -0,0 +1,64 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_occ_runtime_scom.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_occ_runtime_scom.H +/// @brief Core OCC runtime SCOMS +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + + +#ifndef __P9_HCD_CORE_OCC_RUNTIME_SCOM_H__ +#define __P9_HCD_CORE_OCC_RUNTIME_SCOM_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_occ_runtime_scom_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_occ_runtime_scom_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + + +/// @brief Core OCC runtime SCOMS +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// +/// @attr +/// @attritem ATTR_CORE_OCC_SCOM_LOC - EC target, uint32 +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_occ_runtime_scom( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_OCC_RUNTIME_SCOM_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_pcb_arb.C b/src/ppe/hwp/core/p9_hcd_core_pcb_arb.C new file mode 100644 index 0000000..4dbf22e --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_pcb_arb.C @@ -0,0 +1,83 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_pcb_arb.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_pcb_arb.C +/// @brief Core Chiplet PCB Arbitration +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// If CME, +/// 1.Request PCB Mux, via write to PCB_MUX_REQ_C0 @ CCSCR_OR +/// - setBit(5) @ CME_LOCAL_CORE_STOP_CONTROL_REGISTER_OR_0510 +/// 2.Poll for PCB Mux grant, via read from +/// Polled Timeout: ns +/// - getBit() @ +/// Else (SBE), +/// Nop (as the CME is not running in bringing up the first Core) +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_pcb_arb.H" + +//----------------------------------------------------------------------------- +// Constant Definitions: Core Chiplet PCB Arbitration +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_pcb_arb( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) +{ + +#if 0 + + fapi2::buffer<uint64_t> data; + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + diff --git a/src/ppe/hwp/core/p9_hcd_core_pcb_arb.H b/src/ppe/hwp/core/p9_hcd_core_pcb_arb.H new file mode 100644 index 0000000..4029514 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_pcb_arb.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_pcb_arb.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_pcb_arb.H +/// @brief Core Chiplet PCB Arbitration +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + + +#ifndef __P9_HCD_CORE_PCB_ARB_H__ +#define __P9_HCD_CORE_PCB_ARB_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_pcb_arb_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_pcb_arb_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + +/// @brief Core Chiplet PCB Arbitration +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_pcb_arb( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_PCB_ARB_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_poweron.C b/src/ppe/hwp/core/p9_hcd_core_poweron.C new file mode 100644 index 0000000..e215c27 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_poweron.C @@ -0,0 +1,84 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_poweron.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_poweron.C +/// @brief Core Chiplet Power-on +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// 1.Command the core PFET controller to power-on, via putscom to CPPM +/// - +/// 2.Check for valid power on completion, via getscom from CPPM +/// Polled Timeout: 100us +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_poweron.H" + +//----------------------------------------------------------------------------- +// Constant Definitions +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Procedure: Core Chiplet Power-on +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_poweron( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target, + const uint32_t i_operation) +{ + +#if 0 + + fapi2::buffer<uint64_t> data; + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + diff --git a/src/ppe/hwp/core/p9_hcd_core_poweron.H b/src/ppe/hwp/core/p9_hcd_core_poweron.H new file mode 100644 index 0000000..970d1e4 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_poweron.H @@ -0,0 +1,67 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_poweron.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_poweron.H +/// @brief Core Chiplet Power-on +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + + +#ifndef __P9_HCD_CORE_POWERON_H__ +#define __P9_HCD_CORE_POWERON_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_poweron_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_poweron_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&, + const uint32_t); + + +/// @brief Core Chiplet Power-on +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// @param [in] i_operation ENUM(ON,OFF) +/// +/// @attr +/// @attritem ATTR_PFET_* +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_poweron( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target, + const uint32_t i_operation); + + +} // extern C + +#endif // __P9_HCD_CORE_POWERON_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_ras_runtime_scom.C b/src/ppe/hwp/core/p9_hcd_core_ras_runtime_scom.C new file mode 100644 index 0000000..654e24e --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_ras_runtime_scom.C @@ -0,0 +1,165 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_ras_runtime_scom.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_ras_runtime_scom.C +/// @brief FSP/Host run-time SCOMS +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Run-time updates from FSP based PRD, etc that are put on the core image +/// by STOP API calls +/// Dynamically built pointer where a NULL is checked before execution +/// If NULL (the SBE case), return +/// Else call the function at the pointer; +/// pointer is filled in by STOP image build +/// Run-time updates from Host code that are put on the core image by +/// STOP API calls +/// Restore Hypervisor, Host PRD, etc. SCOMs +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_ras_runtime_scom.H" + +//----------------------------------------------------------------------------- +// Constant Definitions +//----------------------------------------------------------------------------- +#define host_runtime_scom 0 + +//----------------------------------------------------------------------------- +// Procedure: FSP/Host run-time SCOMS +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_ras_runtime_scom( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + // Run the SCOM sequence if the SCOM procedure is defined + // - la A0, sp_runtime_scom + // - ld D0, 0, A0 + // - braz D0, 1f + //FAPI_INF("Launching SP Runtime SCOM routine") + // - bsrd D0 + // - 1: + // + + // Run the SCOM sequence if the SCOM procedure is defined. + // - la A0, host_runtime_scom + // - ld D1, 0, A0 + // - braz D1, 1f + + // Prep P1 + // - setp1_mcreadand D0 +#if 0 + // Disable the AISS to allow the override + // - ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + // - andi D0, D0, ~(BIT(1)) + // - std D0, EX_OHA_MODE_REG_RWx1002000D, P0 + // Drop PSCOM fence to allow SCOM and set pm_wake-up to PC to accepts + // RAMs (SCOMs actually) in the IPL "Nap" state + // - ld D0, EX_OHA_AISS_IO_REG_0x10020014, P1 + // - ori D0, D0, (BIT(15)) + // - andi D0, D0, ~(BIT(21)) + // - std D0, EX_OHA_AISS_IO_REG_0x10020014, P0 +#endif + // Branch to sub_slw_runtime_scom() + FAPI_INF("Launching Host Runtime SCOM routine") + // - bsrd D1 + + // Prep P1 + // - setp1_mcreadand D0 +#if 0 + // Clear regular wake-up and restore PSCOM fence in OHA + // These were established in p9_sbe_ex_scominit.S + // - ld D0, EX_OHA_AISS_IO_REG_0x10020014, P1 + // - andi D0, D0, ~(BIT(15)) + // - ori D0, D0, BIT(21) + // - std D0, EX_OHA_AISS_IO_REG_0x10020014, P0 + // Enable the AISS to allow further operation + // - ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + // - ori D0, D0, (BIT(1)) + // - std D0, EX_OHA_MODE_REG_RWx1002000D, P0 +#endif + // - bra 2f + // - 1: + // To accomodate IPL flow, where sub_slw_runtime_scom() is skipped + // - setp1_mcreadand D0 +#if 0 + // Clear regular wake-up and restore PSCOM fence in OHA + // These were established in p9_sbe_ex_scominit.S + // - ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + // - andi D0, D0, ~BIT(1) + // - std D0, EX_OHA_MODE_REG_RWx1002000D, P0 + // - ld D0, EX_OHA_AISS_IO_REG_0x10020014, P1 + // - andi D0, D0, ~(BIT(15)) + // - ori D0, D0, BIT(21) + // - std D0, EX_OHA_AISS_IO_REG_0x10020014, P0 + // Enable the AISS to allow further operation + // - ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + // - ori D0, D0, (BIT(1)) + // - std D0, EX_OHA_MODE_REG_RWx1002000D, P0 +#endif + // - 2: + + // If using cv_multicast, we need to set the magic istep number here + // - la A0, p9_sbe_select_ex_control + // - ldandi D0, 0, A0, P9_CONTROL_INIT_ALL_EX + // - braz D0, 3f + FAPI_DBG("Setting istep num to magic number because cv_multicast is set") + // - lpcs P1, MBOX_SBEVITAL_0x0005001C + // - sti MBOX_SBEVITAL_0x0005001C, P1, (P9_SBE_EX_RAS_RUNTIME_SCOM_MAGIC_ISTEP_NUM << (4+32)) + // - 3: + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/core/p9_hcd_core_ras_runtime_scom.H b/src/ppe/hwp/core/p9_hcd_core_ras_runtime_scom.H new file mode 100644 index 0000000..aca5bc2 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_ras_runtime_scom.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_ras_runtime_scom.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_ras_runtime_scom.H +/// @brief FSP/Host run-time SCOMS +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CORE_RAS_RUNTIME_SCOM_H__ +#define __P9_HCD_CORE_RAS_RUNTIME_SCOM_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_ras_runtime_scom_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_ras_runtime_scom_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + + +/// @brief FSP/Host run-time SCOMS +/// +/// @param [in] i_target TARGET_TYPE_CORE target +// +/// @attr +/// @attritem ATTR_CORE_RAS_SCOM_LOC - EC target, uint32 +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_ras_runtime_scom( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_RAS_RUNTIME_SCOM_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_repair_initf.C b/src/ppe/hwp/core/p9_hcd_core_repair_initf.C new file mode 100644 index 0000000..167c84e --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_repair_initf.C @@ -0,0 +1,89 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_repair_initf.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_repair_initf.C +/// @brief Load Repair ring for core +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Load core ring images from that came from MVPD into the image +/// These rings must contain ALL chip customization data. This includes the +/// following: Array Repair and DTS calibration settings +/// Historically this was stored in MVPD keywords are #R, #G. Still stored +/// in MVPD, but SBE image is customized with rings for booting cores +/// at build time +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_repair_initf.H" + +//----------------------------------------------------------------------------- +// Constant Definitions +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Procedure: Load Repair ring for core +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_repair_initf( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) +{ + +#if 0 + + fapi2::buffer<uint64_t> data; + + // scan chiplet specific ring content + //FAPI_DBG("Scanning EX core REPAIR rings...") + // - load_ring_vec_ex ex_repr_core + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + diff --git a/src/ppe/hwp/core/p9_hcd_core_repair_initf.H b/src/ppe/hwp/core/p9_hcd_core_repair_initf.H new file mode 100644 index 0000000..7c9b831 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_repair_initf.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_repair_initf.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_repair_initf.H +/// @brief Load Repair ring for core +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CORE_REPAIR_INITF_H__ +#define __P9_HCD_CORE_REPAIR_INITF_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_repair_initf_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_repair_initf_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + + +/// @brief Load Repair ring for core +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// @attr +/// @attritem ATTR_CORE_REPAIR_RING - EC target, uint32 +/// pointer to RS4 content +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_repair_initf( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_REPAIR_INITF_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_runinit.C b/src/ppe/hwp/core/p9_hcd_core_runinit.C new file mode 100644 index 0000000..eedc0fe --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_runinit.C @@ -0,0 +1,75 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_runinit.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_runinit.C +/// @brief execute all core init procedures +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_runinit.H" + +//------------------------------------------------------------------------------ +// Constant Definitions: +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Procedure: +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_runinit( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target) +{ + return fapi2::FAPI2_RC_SUCCESS; + +#if 0 + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/core/p9_hcd_core_runinit.H b/src/ppe/hwp/core/p9_hcd_core_runinit.H new file mode 100644 index 0000000..09881a8 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_runinit.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_runinit.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_runinit.H +/// @brief execute all core init procedures +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : CME +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CORE_RUNINIT_H__ +#define __P9_HCD_CORE_RUNINIT_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_runinit_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_runinit_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&); + + +/// @brief Core Customization SCOMs +/// +/// @param [in] i_target TARGET_TYPE_PROC_CHIP target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_runinit( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_RUNINIT_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_scomcust.C b/src/ppe/hwp/core/p9_hcd_core_scomcust.C new file mode 100644 index 0000000..11a1c15 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_scomcust.C @@ -0,0 +1,83 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_scomcust.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_scomcust.C +/// @brief Core Customization SCOMs +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Dynamically built (and installed) routine that is inserted by the .XIP +/// Customization. process. (New for P9) (TODO: this part of the process is +/// a placeholder at this point) +/// Dynamically built pointer where a NULL is checked before execution +/// If NULL (a potential early value); return +/// Else call the function at the pointer; +/// pointer is filled in by XIP Customization +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_scomcust.H" + +//----------------------------------------------------------------------------- +// Constant Definitions: Core Customization SCOMs +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_scomcust( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) +{ + +#if 0 + + fapi2::buffer<uint64_t> data; + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/core/p9_hcd_core_scomcust.H b/src/ppe/hwp/core/p9_hcd_core_scomcust.H new file mode 100644 index 0000000..b9643c6 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_scomcust.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_scomcust.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_scomcust.H +/// @brief Core Customization SCOMs +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + + +#ifndef __P9_HCD_CORE_SCOMCUST_H__ +#define __P9_HCD_CORE_SCOMCUST_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_scomcust_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_scomcust_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + + +/// @brief Core Customization SCOMs +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_scomcust( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + +} // extern C + +#endif // __P9_HCD_CORE_SCOMCUST_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_scominit.C b/src/ppe/hwp/core/p9_hcd_core_scominit.C new file mode 100644 index 0000000..3d4030d --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_scominit.C @@ -0,0 +1,160 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_scominit.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_scominit.C +/// @brief Core SCOM Inits +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Apply any coded SCOM initialization to core +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_scominit.H" + + +//----------------------------------------------------------------------------- +// Constant Definitions +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Procedure: Core SCOM Inits +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_scominit( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) +{ + +#if 0 + fapi2::buffer<uint64_t> data; + + /////////////////// + // Core + /////////////////// + + // Force the hardware to think we're in special wakeup so the SCOMs will + // succeed to the core due to the init state of Nap. This does NOT + // influence the PM state machines; only the wire indicating special + // wake-up using the override in PMGP1 + // Bit 6 enables/disables override; bit 8 controls the Special Wake-up + // = sti EX_PMGP1_OR_0x100F0105, P0, BIT(6) | BIT(8) + FAPI_TRY(putScom(i_target, EX_PMGP1_OR_0x100F0105, + fapi2:buffer<uint64_t>().insertFromRight<6,3>(0x5))); + // - setp1_mcreadand D0 +#if 0 + // Disable the AISS to allow the override + // - ld D0, EX_OHA_MODE_REG_RWx1002000D, P1 + // - andi D0, D0, ~(BIT(1)) + // - std D0, EX_OHA_MODE_REG_RWx1002000D, P0 + // Drop PSCOM fence to allow SCOM and set pm_wake-up to PC to accepts + // RAMs (SCOMs actually) in the IPL "Nap" state + // - ld D0, EX_OHA_AISS_IO_REG_0x10020014, P1 + // - ori D0, D0, (BIT(15)) + // - andi D0, D0, ~(BIT(21)) + // - std D0, EX_OHA_AISS_IO_REG_0x10020014, P0 +#endif + //CMO-> Should prob reenable AISS here. But carefully... + + // These are dropped in p9_sbe_ex_host_runtime_scom.S + + /////////////////// + // Clock Controller + /////////////////// + + // Set the OPCG_PAD_VALUE to be fast enough to not allow overrun by the + // OHA in for Deep Sleep Exit. Set for 32 cycles (2 x 16) -> 0b010 + FAPI_INF("Setup OPCG_PAD_VALUE for Deep Sleep scanning ...") + // - ld D1, EX_OPCG_CNTL2_0x10030004, P1 + // - andi D1, D1, ~(BITS(49,3)) + // - ori D1, D1, BIT(50) + // - std D1, EX_OPCG_CNTL2_0x10030004, P0 + FAPI_TRY(getScom(i_target, EX_OPCG_CNTL2_0x10030004, data)); + data.insertFromRight<49,3>(0x2); + FAPI_TRY(putScom(i_target, EX_OPCG_CNTL2_0x10030004, data)); + + /////////////////// + // L2 + /////////////////// + + // set L2 inits to force single member mode if required + FAPI_DBG("Configuring L2 single member mode ..."); + // - l2_single_member + + // set L2 inits to disable L3 if required + FAPI_DBG("Configuring L3 disable ..."); + // - l3_setup L3_SETUP_ACTION_DISABLE, L3_SETUP_UNIT_L2 + + /////////////////// + // DTS + /////////////////// + + // As this routine get runs for IPL, Winkle and Sleep, all Digital + // Thermal Sensor setup is done here. + // For the case of Sleep where the L3 DTS is still active, the + // initialization is redone anyway as, while this operation is going on, + // the atomic lock prevents other entities (eg OCC) from accessing it. + // This keep the flows the same. + + // - setp1_mcreadand D0 + FAPI_INF("Initialize DTS function ...") + + // Enable DTS sampling - bit 5 + // Sample Pulse Count - bits(6:9) set to a small number for sim + // Enable loop 1 DTSs (20:22); loop 2 DTSs (24) + // = ld D1, EX_THERM_MODE_REG_0x1005000F, P1 + // = ori D1, D1, (BIT(5)|BITS(6, 4)|BITS(20,3)|BIT(24)) + // = std D1, EX_THERM_MODE_REG_0x1005000F, P0 + FAPI_TRY(getScom(i_target, EX_THERM_MODE_REG_0x1005000F, data)); + data.insertFromRight<5,5>(0x1F).insertFromRight<20,3>(0xF).setBit<24>(); + FAPI_TRY(putScom(i_target, EX_THERM_MODE_REG_0x1005000F, data)); + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + diff --git a/src/ppe/hwp/core/p9_hcd_core_scominit.H b/src/ppe/hwp/core/p9_hcd_core_scominit.H new file mode 100644 index 0000000..9cb570a --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_scominit.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_scominit.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_scominit.H +/// @brief Core SCOM Inits +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + + +#ifndef __P9_HCD_CORE_SCOMINIT_H__ +#define __P9_HCD_CORE_SCOMINIT_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_scominit_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_scominit_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + + +/// @brief Core SCOM Inits +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_scominit( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_SCOMINIT_H__ diff --git a/src/ppe/hwp/core/p9_hcd_core_startclocks.C b/src/ppe/hwp/core/p9_hcd_core_startclocks.C new file mode 100644 index 0000000..012f533 --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_startclocks.C @@ -0,0 +1,97 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_startclocks.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_startclocks.C +/// @brief Core Clock Start +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// Drop pervasive thold +/// Drop pervasive fence +/// Reset abst clock muxsel, sync muxsel +/// Clear clock controller scan register before start +/// Start arrays + nsl regions +/// Start sl + refresh clock regions +/// Check for clocks started +/// If not, error +/// Check for core xstop (TODO: need for this (?) and then FIR structure in +/// for P9. Note: CME can NOT read Cache FIR) +/// If so, error +/// Clear force align +/// Clear flush mode +/// Check security switch and set trusted boot en bit +/// (TODO: still needed for P9?) +/// Drop the core to cache logical fence +/// + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_hcd_core_startclocks.H" + +//----------------------------------------------------------------------------- +// Constant Definitions +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Procedure: Core Clock Start +//----------------------------------------------------------------------------- + +extern "C" +{ + +fapi2::ReturnCode +p9_hcd_core_startclocks( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target) +{ + +#if 0 + + fapi2::buffer<uint64_t> data; + + return fapi2::FAPI2_RC_SUCCESS; + + FAPI_CLEANUP(); + return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + +#endif + + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + + diff --git a/src/ppe/hwp/core/p9_hcd_core_startclocks.H b/src/ppe/hwp/core/p9_hcd_core_startclocks.H new file mode 100644 index 0000000..38b6fbd --- /dev/null +++ b/src/ppe/hwp/core/p9_hcd_core_startclocks.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/core/p9_hcd_core_startclocks.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_hcd_core_startclocks.H +/// @brief Core Clock Start +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:CME +/// *HWP Level : 1 +/// + +#ifndef __P9_HCD_CORE_STARTCLOCKS_H__ +#define __P9_HCD_CORE_STARTCLOCKS_H__ + +extern "C" +{ + +/// @typedef p9_hcd_core_startclocks_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_hcd_core_startclocks_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>&); + +/// @brief Core Clock Start +/// +/// @param [in] i_target TARGET_TYPE_CORE target +/// +/// @attr +/// @attritem NONE +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_hcd_core_startclocks( + const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target); + + +} // extern C + +#endif // __P9_HCD_CORE_STARTCLOCKS_H__ diff --git a/src/ppe/hwp/lib/Makefile b/src/ppe/hwp/lib/Makefile new file mode 100644 index 0000000..360d012 --- /dev/null +++ b/src/ppe/hwp/lib/Makefile @@ -0,0 +1,54 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/hwp/lib/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 + +# This Makefile compiles all of the common library hardware procedure code. +# See the "libcommonfiles.mk" file in this directory. + +#all generated files from this makefile will end up in obj/lib +export SUB_OBJDIR = /lib + +include img_defs.mk +include libcommonfiles.mk + + +OBJS := $(addprefix $(OBJDIR)/, $(LIB_OBJECTS)) + +libcommon.a: lib + $(AR) crs $(OBJDIR)/libcommon.a $(OBJDIR)/*.o + +.PHONY: clean lib +lib: $(OBJS) + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +clean: + rm -fr $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/hwp/lib/libcommonfiles.mk b/src/ppe/hwp/lib/libcommonfiles.mk new file mode 100644 index 0000000..854d71b --- /dev/null +++ b/src/ppe/hwp/lib/libcommonfiles.mk @@ -0,0 +1,53 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/hwp/lib/libcommonfiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file libcommonfiles.mk +# +# @brief mk for including library common object files +# +# @page ChangeLogs Change Logs +# @section libcommonfiles.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# Object Files +########################################################################## + +LIB-CPP-SOURCES += p9_common_poweronoff.C +LIB-CPP-SOURCES += p9_common_pro_epi_log.C + +LIB-C-SOURCES += +LIB-S-SOURCES += + +LIB_OBJECTS += $(LIB-CPP-SOURCES:.C=.o) +LIB_OBJECTS += $(LIB-C-SOURCES:.c=.o) +LIB_OBJECTS += $(LIB-S-SOURCES:.S=.o) + diff --git a/src/ppe/hwp/lib/p9_common_poweronoff.C b/src/ppe/hwp/lib/p9_common_poweronoff.C new file mode 100644 index 0000000..cd5e6f8 --- /dev/null +++ b/src/ppe/hwp/lib/p9_common_poweronoff.C @@ -0,0 +1,71 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/lib/p9_common_poweronoff.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_common_poweronoff.C +/// @brief common procedure for power on/off +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE:CME +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_common_poweronoff.H" + +//------------------------------------------------------------------------------ +// Constant Definitions: +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Procedure: +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_common_poweronoff( + const fapi2::Target<fapi2::TARGET_TYPE_EQ| + fapi2::TARGET_TYPE_CORE>& i_target, + int i_operation) +{ + return fapi2::FAPI2_RC_SUCCESS; + + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/lib/p9_common_poweronoff.H b/src/ppe/hwp/lib/p9_common_poweronoff.H new file mode 100644 index 0000000..a5bd036 --- /dev/null +++ b/src/ppe/hwp/lib/p9_common_poweronoff.H @@ -0,0 +1,68 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/lib/p9_common_poweronoff.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_common_poweronoff.H +/// @brief common procedure for power on/off +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE:CME +/// *HWP Level : 1 +/// + +#ifndef __P9_COMMON_POWERONOFF_H__ +#define __P9_COMMON_POWERONOFF_H__ + +extern "C" +{ + +/// @typedef p9_common_proweronoff_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_common_proweronoff_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EQ| + fapi2::TARGET_TYPE_CORE>&, + int); + + +/// @brief common procedure for power on/off +/// +/// @param [in] i_target TARGET_TYPE_EQ|TARGET_TYPE_CORE target +/// @param [in] i_operation ENUM(ON,OFF) +/// +/// @attr +/// @attritem ATTR_PFET_TIMING - EX target, uint32 +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_common_proweronoff( + const fapi2::Target<fapi2::TARGET_TYPE_EQ| + fapi2::TARGET_TYPE_CORE>& i_target, + int i_operation); + + +} // extern C + +#endif // __P9_COMMON_POWERONOFF_H__ diff --git a/src/ppe/hwp/lib/p9_common_pro_epi_log.C b/src/ppe/hwp/lib/p9_common_pro_epi_log.C new file mode 100644 index 0000000..33237cd --- /dev/null +++ b/src/ppe/hwp/lib/p9_common_pro_epi_log.C @@ -0,0 +1,70 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/lib/p9_common_pro_epi_log.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_common_pro_epi_log.C +/// @brief common procedure prologue/epilogue routines +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// +/// Procedure Summary: +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +//#include <common_scom_addresses.H> +//will be replaced with real scom address header file +#include "p9_common_pro_epi_log.H" + +//------------------------------------------------------------------------------ +// Constant Definitions: +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Procedure: +//------------------------------------------------------------------------------ + +extern "C" +{ + +fapi2::ReturnCode +p9_common_pro_epi_log( + const fapi2::Target<fapi2::TARGET_TYPE_EQ | + fapi2::TARGET_TYPE_CORE>& i_target, + int i_operation) +{ + return fapi2::FAPI2_RC_SUCCESS; + +} // Procedure + + +} // extern C + + diff --git a/src/ppe/hwp/lib/p9_common_pro_epi_log.H b/src/ppe/hwp/lib/p9_common_pro_epi_log.H new file mode 100644 index 0000000..b119b37 --- /dev/null +++ b/src/ppe/hwp/lib/p9_common_pro_epi_log.H @@ -0,0 +1,68 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/lib/p9_common_pro_epi_log.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file p9_common_pro_epi_log.H +/// @brief common procedure prologue/epilogue routines +/// +/// *HWP HWP Owner : David Du <daviddu@us.ibm.com> +/// *HWP FW Owner : Reshmi Nair <resnair5@in.ibm.com> +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE +/// *HWP Level : 1 +/// + +#ifndef __P9_COMMON_PRO_EPI_LOG_H__ +#define __P9_COMMON_PRO_EPI_LOG_H__ + +extern "C" +{ + +/// @typedef p9_common_pro_epi_log_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_common_pro_epi_log_FP_t) ( + const fapi2::Target<fapi2::TARGET_TYPE_EQ| + fapi2::TARGET_TYPE_CORE>&, + int); + + +/// @brief common procedure prologue/epilogue routines +/// +/// @param [in] i_target TARGET_TYPE_EQ|TARGET_TYPE_CORE target +/// @param [in] i_operation ENUM(PROLOG, EPILOG) +/// +/// @attr +/// @attritem ATTR_EX_PARIAL_GOOD - EX target, uint32 +/// +/// @retval FAPI_RC_SUCCESS +fapi2::ReturnCode +p9_common_pro_epi_log( + const fapi2::Target<fapi2::TARGET_TYPE_EQ| + fapi2::TARGET_TYPE_CORE>& i_target, + int i_operation); + + +} // extern C + +#endif // __P9_COMMON_PRO_EPI_LOG_H__ diff --git a/src/ppe/hwp/nest/.empty b/src/ppe/hwp/nest/.empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/hwp/nest/.empty diff --git a/src/ppe/hwp/perv/.empty b/src/ppe/hwp/perv/.empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/hwp/perv/.empty diff --git a/src/ppe/hwp/perv/Makefile b/src/ppe/hwp/perv/Makefile new file mode 100644 index 0000000..68a803f --- /dev/null +++ b/src/ppe/hwp/perv/Makefile @@ -0,0 +1,54 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/hwp/perv/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 + +# This Makefile compiles all of the core hardware procedure code. See the +# "pervfiles.mk" file in this directory. + +#all generated files from this makefile will end up in obj/perv +export SUB_OBJDIR = /perv + +include img_defs.mk +include pervfiles.mk + + +OBJS := $(addprefix $(OBJDIR)/, $(PERV_OBJECTS)) + +libperv.a: perv + $(AR) crs $(OBJDIR)/libperv.a $(OBJDIR)/*.o + +.PHONY: clean perv +perv: $(OBJS) + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +clean: + rm -fr $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/hwp/perv/p9_sbe_attr_setup.C b/src/ppe/hwp/perv/p9_sbe_attr_setup.C new file mode 100644 index 0000000..cc08372 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_attr_setup.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_attr_setup.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_attr_setup.C +/// +/// @brief If and only if scratch registers are non-zero, HWP will read the contents of the scratch registers and call FAPI2 APIs to set the values into the corresponding platform ATTR +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_attr_setup.H" +fapi2::ReturnCode p9_sbe_attr_setup(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_attr_setup: Entering ..."); + + FAPI_DBG("p9_sbe_attr_setup: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_attr_setup.H b/src/ppe/hwp/perv/p9_sbe_attr_setup.H new file mode 100644 index 0000000..d392969 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_attr_setup.H @@ -0,0 +1,61 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_attr_setup.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_attr_setup.H +/// +/// @brief If and only if scratch registers are non-zero, HWP will read the contents of the scratch registers and call FAPI2 APIs to set the values into the corresponding platform ATTR +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_ATTR_SETUP_H_ +#define _P9_SBE_ATTR_SETUP_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_attr_setup_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief --Setting All Mailbox scratch register 1, 2, 3, 4, 5, 6, 7, 8 +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_attr_setup(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_check_master.C b/src/ppe/hwp/perv/p9_sbe_check_master.C new file mode 100644 index 0000000..b348bdf --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_check_master.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_check_master.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_check_master.C +/// +/// @brief Deremine if this is master SBE -- External FSI/GP bitIf master continue, else enable runtime chipOps +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_check_master.H" +fapi2::ReturnCode p9_sbe_check_master(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_check_master: Entering ..."); + + FAPI_DBG("p9_sbe_check_master: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_check_master.H b/src/ppe/hwp/perv/p9_sbe_check_master.H new file mode 100644 index 0000000..04a1748 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_check_master.H @@ -0,0 +1,61 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_check_master.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_check_master.H +/// +/// @brief Deremine if this is master SBE -- External FSI/GP bitIf master continue, else enable runtime chipOps +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_CHECK_MASTER_H_ +#define _P9_SBE_CHECK_MASTER_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_check_master_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief If master continue, else enable runtime chipOps +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_check_master(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_enable_seeprom.C b/src/ppe/hwp/perv/p9_sbe_enable_seeprom.C new file mode 100644 index 0000000..eab78e2 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_enable_seeprom.C @@ -0,0 +1,53 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_enable_seeprom.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_enable_seeprom.C +/// +/// @brief SBE enable SEEPROM (runs from OTPROM) +/// +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_enable_seeprom.H" +fapi2::ReturnCode p9_sbe_enable_seeprom(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_enable_seeprom: Entering ..."); + + FAPI_DBG("p9_sbe_enable_seeprom: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_enable_seeprom.H b/src/ppe/hwp/perv/p9_sbe_enable_seeprom.H new file mode 100644 index 0000000..e74e114 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_enable_seeprom.H @@ -0,0 +1,67 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_enable_seeprom.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_enable_seeprom.H +/// +/// @brief SBE enable SEEPROM (runs from OTPROM) +/// +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_ENABLE_SEEPROM_H_ +#define _P9_SBE_ENABLE_SEEPROM_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_enable_seeprom_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief -- Check SBE Vital Register for selected SEEPROM image +/// -- Update SBE FI2C_E0_PARAM register +/// -- Check for valid SEEPROM image +/// -- Branch to SEEPROM +/// +/// +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_enable_seeprom(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_lpc_init.C b/src/ppe/hwp/perv/p9_sbe_lpc_init.C new file mode 100644 index 0000000..533bad3 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_lpc_init.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_lpc_init.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_lpc_init.C +/// +/// @brief Requirement from the bootloader is that it only uses MMIOs to LPC master, not Xscom +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_lpc_init.H" +fapi2::ReturnCode p9_sbe_lpc_init(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_lpc_init: Entering ..."); + + FAPI_DBG("p9_sbe_lpc_init: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_lpc_init.H b/src/ppe/hwp/perv/p9_sbe_lpc_init.H new file mode 100644 index 0000000..859f7bf --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_lpc_init.H @@ -0,0 +1,65 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_lpc_init.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_lpc_init.H +/// +/// @brief Requirement from the bootloader is that it only uses MMIOs to LPC master, not Xscom +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_LPC_INIT_H_ +#define _P9_SBE_LPC_INIT_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_lpc_init_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief PerfoPerform scoms to setup LPC bus +/// -- Move the LPC clock to external input +/// Pull the LPC unit out of reset +/// Set LPC BAR -- hardcoded like Xscom BAR +/// +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_lpc_init(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_nest_arrayinit.C b/src/ppe/hwp/perv/p9_sbe_nest_arrayinit.C new file mode 100644 index 0000000..141f29a --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_arrayinit.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_arrayinit.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_arrayinit.C +/// +/// @brief array init for nest chiplet arrays +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_nest_arrayinit.H" +fapi2::ReturnCode p9_sbe_nest_arrayinit(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_nest_arrayinit: Entering ..."); + + FAPI_DBG("p9_sbe_nest_arrayinit: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_nest_arrayinit.H b/src/ppe/hwp/perv/p9_sbe_nest_arrayinit.H new file mode 100644 index 0000000..33deab2 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_arrayinit.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_arrayinit.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_arrayinit.H +/// +/// @brief array init for nest chiplet arrays +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_NEST_ARRAYINIT_H_ +#define _P9_SBE_NEST_ARRAYINIT_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_nest_arrayinit_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief --Run arrayinit on all enabled chiplets +/// --Scan flush 0 to all rings except GPTR, Time, Repair on all enabled chiplets +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_nest_arrayinit(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_nest_chiplet_init.C b/src/ppe/hwp/perv/p9_sbe_nest_chiplet_init.C new file mode 100644 index 0000000..d60414b --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_chiplet_init.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_chiplet_init.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_chiplet_init.C +/// +/// @brief proc sbe nest chiplet init +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_nest_chiplet_init.H" +fapi2::ReturnCode p9_sbe_nest_chiplet_init(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_nest_chiplet_init: Entering ..."); + + FAPI_DBG("p9_sbe_nest_chiplet_init: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_nest_chiplet_init.H b/src/ppe/hwp/perv/p9_sbe_nest_chiplet_init.H new file mode 100644 index 0000000..795e3a6 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_chiplet_init.H @@ -0,0 +1,61 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_chiplet_init.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_chiplet_init.H +/// +/// @brief proc sbe nest chiplet init +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_NEST_CHIPLET_INIT_H_ +#define _P9_SBE_NEST_CHIPLET_INIT_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_nest_chiplet_init_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief --Scan 0 all rings (except time, repair, gptr) on all enabled chiplets +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_nest_chiplet_init(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_nest_chiplet_reset.C b/src/ppe/hwp/perv/p9_sbe_nest_chiplet_reset.C new file mode 100644 index 0000000..4a8626d --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_chiplet_reset.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_chiplet_reset.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_chiplet_reset.C +/// +/// @brief proc nest chiplet reset +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_nest_chiplet_reset.H" +fapi2::ReturnCode p9_sbe_nest_chiplet_reset(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_nest_chiplet_reset: Entering ..."); + + FAPI_DBG("p9_sbe_nest_chiplet_reset: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_nest_chiplet_reset.H b/src/ppe/hwp/perv/p9_sbe_nest_chiplet_reset.H new file mode 100644 index 0000000..e9922eb --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_chiplet_reset.H @@ -0,0 +1,61 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_chiplet_reset.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_chiplet_reset.H +/// +/// @brief proc nest chiplet reset +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_NEST_CHIPLET_RESET_H_ +#define _P9_SBE_NEST_CHIPLET_RESET_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_nest_chiplet_reset_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief Reset Nest chiplet +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_nest_chiplet_reset(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_nest_gptr_time_repr_initf.C b/src/ppe/hwp/perv/p9_sbe_nest_gptr_time_repr_initf.C new file mode 100644 index 0000000..c06d950 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_gptr_time_repr_initf.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_gptr_time_repr_initf.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_gptr_time_repr_initf.C +/// +/// @brief proc sbe nest gptr time repr initf +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_nest_gptr_time_repr_initf.H" +fapi2::ReturnCode p9_sbe_nest_gptr_time_repr_initf(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_nest_gptr_time_repr_initf: Entering ..."); + + FAPI_DBG("p9_sbe_nest_gptr_time_repr_initf: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_nest_gptr_time_repr_initf.H b/src/ppe/hwp/perv/p9_sbe_nest_gptr_time_repr_initf.H new file mode 100644 index 0000000..b37145b --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_gptr_time_repr_initf.H @@ -0,0 +1,61 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_gptr_time_repr_initf.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_gptr_time_repr_initf.H +/// +/// @brief proc sbe nest gptr time repr initf +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_NEST_GPTR_TIME_REPR_INITF_H_ +#define _P9_SBE_NEST_GPTR_TIME_REPR_INITF_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_nest_gptr_time_repr_initf_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief Scan 0 all rings on all enabled chiplets (except for TP) +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_nest_gptr_time_repr_initf(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_nest_initf.C b/src/ppe/hwp/perv/p9_sbe_nest_initf.C new file mode 100644 index 0000000..c8bd4a7 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_initf.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_initf.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_initf.C +/// +/// @brief proc_sbe_nest_initf +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_nest_initf.H" +fapi2::ReturnCode p9_sbe_nest_initf(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_nest_initf: Entering ..."); + + FAPI_DBG("p9_sbe_nest_initf: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_nest_initf.H b/src/ppe/hwp/perv/p9_sbe_nest_initf.H new file mode 100644 index 0000000..2add6ac --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_initf.H @@ -0,0 +1,61 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_initf.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_initf.H +/// +/// @brief proc_sbe_nest_initf +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_NEST_INITF_H_ +#define _P9_SBE_NEST_INITF_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_nest_initf_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief apply init file +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_nest_initf(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_nest_startclocks.C b/src/ppe/hwp/perv/p9_sbe_nest_startclocks.C new file mode 100644 index 0000000..d44835d --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_startclocks.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_startclocks.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_startclocks.C +/// +/// @brief start clocks for nest chiplets +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_nest_startclocks.H" +fapi2::ReturnCode p9_sbe_nest_startclocks(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_nest_startclocks: Entering ..."); + + FAPI_DBG("p9_sbe_nest_startclocks: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_nest_startclocks.H b/src/ppe/hwp/perv/p9_sbe_nest_startclocks.H new file mode 100644 index 0000000..e4644c9 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_nest_startclocks.H @@ -0,0 +1,68 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_nest_startclocks.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_nest_startclocks.H +/// +/// @brief start clocks for nest chiplets +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_NEST_STARTCLOCKS_H_ +#define _P9_SBE_NEST_STARTCLOCKS_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_nest_startclocks_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief --drop vital fence +/// --reset abstclk muxsel and syncclk muxsel +/// --Module align chiplets +/// --Module clock start stop +/// --Check clock stat SL, NSL , ARY +/// --drop chiplet fence +/// --check checkstop register +/// --clear flush inhibit to go into flush mode +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_nest_startclocks(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_npll_initf.C b/src/ppe/hwp/perv/p9_sbe_npll_initf.C new file mode 100644 index 0000000..d40f141 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_npll_initf.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_npll_initf.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_npll_initf.C +/// +/// @brief apply initfile for level 0 & 1 PLLs +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_npll_initf.H" +fapi2::ReturnCode p9_sbe_npll_initf(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_npll_initf: Entering ..."); + + FAPI_DBG("p9_sbe_npll_initf: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_npll_initf.H b/src/ppe/hwp/perv/p9_sbe_npll_initf.H new file mode 100644 index 0000000..8445de1 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_npll_initf.H @@ -0,0 +1,64 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_npll_initf.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_npll_initf.H +/// +/// @brief apply initfile for level 0 & 1 PLLs +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_NPLL_INITF_H_ +#define _P9_SBE_NPLL_INITF_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_npll_initf_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief --run scan0 module (scan region = PLL, scan_types = GPTR) +/// --run scan0 module (scan region = PLL, scan_types = BNDY/FUNC) +/// --Scan initialize PLL BNDY chain (chiplet = PERV, scan ring = PLL, scan type = BNDY) +/// +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_npll_initf(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_npll_setup.C b/src/ppe/hwp/perv/p9_sbe_npll_setup.C new file mode 100644 index 0000000..1a66606 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_npll_setup.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_npll_setup.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_npll_setup.C +/// +/// @brief scan initialize level 0 & 1 PLLs +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_npll_setup.H" +fapi2::ReturnCode p9_sbe_npll_setup(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_npll_setup: Entering ..."); + + FAPI_DBG("p9_sbe_npll_setup: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_npll_setup.H b/src/ppe/hwp/perv/p9_sbe_npll_setup.H new file mode 100644 index 0000000..bcc5f01 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_npll_setup.H @@ -0,0 +1,73 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_npll_setup.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_npll_setup.H +/// +/// @brief scan initialize level 0 & 1 PLLs +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_NPLL_SETUP_H_ +#define _P9_SBE_NPLL_SETUP_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_npll_setup_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief --Release PLL test enable for SS, Filt & NEST PLLs +/// --Release SS PLL reset0 +/// --check SS PLL lock +/// --Release SS PLL bypass0 +/// --Release Filter PLL reset1 +/// --check PLL lock for Filter PLLs +/// --Release Filter PLL bypass signals +/// --Switch MC meshs to Nest mesh +/// --Release test_pll_bypass2 +/// --Release Tank PLL reset2 +/// --check Nest PLL lock +/// --Release Tank PLL bypass2 +/// +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_npll_setup(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_select_ex.C b/src/ppe/hwp/perv/p9_sbe_select_ex.C new file mode 100644 index 0000000..1976840 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_select_ex.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_select_ex.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_select_ex.C +/// +/// @brief proc sbe select ex +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_select_ex.H" +fapi2::ReturnCode p9_sbe_select_ex(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_select_ex: Entering ..."); + + FAPI_DBG("p9_sbe_select_ex: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_select_ex.H b/src/ppe/hwp/perv/p9_sbe_select_ex.H new file mode 100644 index 0000000..a62d1dd --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_select_ex.H @@ -0,0 +1,66 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_select_ex.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_select_ex.H +/// +/// @brief proc sbe select ex +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_SELECT_EX_H_ +#define _P9_SBE_SELECT_EX_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_select_ex_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief ATTR will indicate single core or all +/// Use the partial good info and ATTR to find the first good core +/// For selected master EQ and Core +/// -- Turn on chiplet enable +/// Write selected EQ/Core mask into OCC complex +/// -- This is the "master record " of the enabled cores/quad in the system +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_select_ex(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_tp_arrayinit.C b/src/ppe/hwp/perv/p9_sbe_tp_arrayinit.C new file mode 100644 index 0000000..0371235 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_arrayinit.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_arrayinit.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_arrayinit.C +/// +/// @brief SBE PRV Array Init Procedure +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_tp_arrayinit.H" +fapi2::ReturnCode p9_sbe_tp_arrayinit(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_tp_arrayinit: Entering ..."); + + FAPI_DBG("p9_sbe_tp_arrayinit: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_tp_arrayinit.H b/src/ppe/hwp/perv/p9_sbe_tp_arrayinit.H new file mode 100644 index 0000000..5ece4e4 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_arrayinit.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_arrayinit.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_arrayinit.H +/// +/// @brief SBE PRV Array Init Procedure +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_TP_ARRAYINIT_H_ +#define _P9_SBE_TP_ARRAYINIT_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_tp_arrayinit_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief -- Array Init for PRV Cplt +/// -- Scan0 of PRV Chiplet (except PIB/PCB) +/// +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_tp_arrayinit(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init1.C b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init1.C new file mode 100644 index 0000000..4756b0b --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init1.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_chiplet_init1.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_chiplet_init1.C +/// +/// @brief IPL STEP 2.3: SBE TP Chiplet Init 1 :: Releases PCB Reset, Sets TP chiplet enable, Drops Perv chiplet fence +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_tp_chiplet_init1.H" +fapi2::ReturnCode p9_sbe_tp_chiplet_init1(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_tp_chiplet_init1: Entering ..."); + + FAPI_DBG("p9_sbe_tp_chiplet_init1: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init1.H b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init1.H new file mode 100644 index 0000000..601c167 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init1.H @@ -0,0 +1,65 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_chiplet_init1.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_chiplet_init1.H +/// +/// @brief IPL STEP 2.3: SBE TP Chiplet Init 1 :: Releases PCB Reset, Sets TP chiplet enable, Drops Perv chiplet fence +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_TP_CHIPLET_INIT1_H_ +#define _P9_SBE_TP_CHIPLET_INIT1_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_tp_chiplet_init1_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief DESCRIPTION -- Drop VSS2VIO fence +/// -- Releases PCB reset +/// -- Sets PRV Chiplet Enable +/// -- Drops PRV Chiplet fence enable +/// -- Drop Global Endpoint Reset +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_tp_chiplet_init1(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init2.C b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init2.C new file mode 100644 index 0000000..36ebf0f --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init2.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_chiplet_init2.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_chiplet_init2.C +/// +/// @brief IPL STEP 2.10 : SBE TP Chiplet Init2 :: Run scan 0 module for pervasive +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_tp_chiplet_init2.H" +fapi2::ReturnCode p9_sbe_tp_chiplet_init2(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_tp_chiplet_init2: Entering ..."); + + FAPI_DBG("p9_sbe_tp_chiplet_init2: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init2.H b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init2.H new file mode 100644 index 0000000..d37e8be --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init2.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_chiplet_init2.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_chiplet_init2.H +/// +/// @brief IPL STEP 2.10 : SBE TP Chiplet Init2 :: Run scan 0 module for pervasive +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_TP_CHIPLET_INIT2_H_ +#define _P9_SBE_TP_CHIPLET_INIT2_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_tp_chiplet_init2_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief -- Initialize TP Hangcounter 6 +/// -- Scan Repair, Time and GPTR for PRV Chiplet +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_tp_chiplet_init2(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init3.C b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init3.C new file mode 100644 index 0000000..80cb27e --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init3.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_chiplet_init3.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_chiplet_init3.C +/// +/// @brief SBE Pervasive Init Procedure 3 +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_tp_chiplet_init3.H" +fapi2::ReturnCode p9_sbe_tp_chiplet_init3(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_tp_chiplet_init3: Entering ..."); + + FAPI_DBG("p9_sbe_tp_chiplet_init3: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init3.H b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init3.H new file mode 100644 index 0000000..25c1c2e --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_init3.H @@ -0,0 +1,68 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_chiplet_init3.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_chiplet_init3.H +/// +/// @brief SBE Pervasive Init Procedure 3 +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_TP_CHIPLET_INIT3_H_ +#define _P9_SBE_TP_CHIPLET_INIT3_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_tp_chiplet_init3_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief -- Switches PRV Chiplet OOB mux +/// -- Reset PCB Master Interrupt Register +/// -- Drop Pervasive and OCC2PIB Fence in GP0 (bits 19 & 63) +/// --"Clock Start" command (all other clk domains) +/// -- Clear force_align in chiplet GP0 +/// -- Clear flushmode_inhibit in chiplet GP0 +/// -- Drop FSI fence 5 (checkstop, interrupt conditions) +/// +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_tp_chiplet_init3(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_tp_chiplet_reset.C b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_reset.C new file mode 100644 index 0000000..bc90079 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_reset.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_chiplet_reset.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_chiplet_reset.C +/// +/// @brief IPL STEP 2.8 : SBE TP Chiplet Reset :: setup hangcounter 6 for TP chiplet +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_tp_chiplet_reset.H" +fapi2::ReturnCode p9_sbe_tp_chiplet_reset(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_tp_chiplet_reset: Entering ..."); + + FAPI_DBG("p9_sbe_tp_chiplet_reset: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_tp_chiplet_reset.H b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_reset.H new file mode 100644 index 0000000..9f3c7ae --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_chiplet_reset.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_chiplet_reset.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_chiplet_reset.H +/// +/// @brief IPL STEP 2.8 : SBE TP Chiplet Reset :: setup hangcounter 6 for TP chiplet +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_TP_CHIPLET_RESET_H_ +#define _P9_SBE_TP_CHIPLET_RESET_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_tp_chiplet_reset_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief --Setup hang counter for PCB slaves/master +/// +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_tp_chiplet_reset(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_tp_gptr_time_repr_initf.C b/src/ppe/hwp/perv/p9_sbe_tp_gptr_time_repr_initf.C new file mode 100644 index 0000000..57ebc5f --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_gptr_time_repr_initf.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_gptr_time_repr_initf.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_gptr_time_repr_initf.C +/// +/// @brief proc sbe tp gptr time repr initf +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_tp_gptr_time_repr_initf.H" +fapi2::ReturnCode p9_sbe_tp_gptr_time_repr_initf(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_tp_gptr_time_repr_initf: Entering ..."); + + FAPI_DBG("p9_sbe_tp_gptr_time_repr_initf: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_tp_gptr_time_repr_initf.H b/src/ppe/hwp/perv/p9_sbe_tp_gptr_time_repr_initf.H new file mode 100644 index 0000000..43e777a --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_gptr_time_repr_initf.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_gptr_time_repr_initf.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_gptr_time_repr_initf.H +/// +/// @brief proc sbe tp gptr time repr initf +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_TP_GPTR_TIME_REPR_INITF_H_ +#define _P9_SBE_TP_GPTR_TIME_REPR_INITF_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_tp_gptr_time_repr_initf_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief --Load Scan Repair, Time and GPTR for TP Chiplet +/// +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_tp_gptr_time_repr_initf(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_tp_initf.C b/src/ppe/hwp/perv/p9_sbe_tp_initf.C new file mode 100644 index 0000000..908cfad --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_initf.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_initf.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_initf.C +/// +/// @brief TP chiplet scaninits for the TP rings +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_tp_initf.H" +fapi2::ReturnCode p9_sbe_tp_initf(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_tp_initf: Entering ..."); + + FAPI_DBG("p9_sbe_tp_initf: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_tp_initf.H b/src/ppe/hwp/perv/p9_sbe_tp_initf.H new file mode 100644 index 0000000..56c2cd1 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_initf.H @@ -0,0 +1,65 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_initf.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_initf.H +/// +/// @brief TP chiplet scaninits for the TP rings +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_TP_INITF_H_ +#define _P9_SBE_TP_INITF_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_tp_initf_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief -- This doesn't include the gptr/time/repair rings, +/// -- since they are scanned in tp_chiplet_init2. +/// -- This doesn't include the net/pib/fuse rings, +/// -- since they are used by the SBE hardware itself. +/// +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_tp_initf(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_tp_ld_image.C b/src/ppe/hwp/perv/p9_sbe_tp_ld_image.C new file mode 100644 index 0000000..2741796 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_ld_image.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_ld_image.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_ld_image.C +/// +/// @brief Proc SBE load Image +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_tp_ld_image.H" +fapi2::ReturnCode p9_sbe_tp_ld_image(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_tp_ld_image: Entering ..."); + + FAPI_DBG("p9_sbe_tp_ld_image: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_tp_ld_image.H b/src/ppe/hwp/perv/p9_sbe_tp_ld_image.H new file mode 100644 index 0000000..3e13af6 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_ld_image.H @@ -0,0 +1,65 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_ld_image.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_ld_image.H +/// +/// @brief Proc SBE load Image +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_TP_LD_IMAGE_H_ +#define _P9_SBE_TP_LD_IMAGE_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_tp_ld_image_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief This procedure copies the .pibmem0 section of image from SEEPROM to the PIBMEM. +/// The pibmem0 section contains the PORE branch table (error handlers) used for the majority of the SEEPROM IPL as well as +/// performance sensitive routines such as the decompression-scan routine and the LCO loader. +/// Once the image is loaded then the error handlers are switched to +/// +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_tp_ld_image(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_sbe_tp_switch_gears.C b/src/ppe/hwp/perv/p9_sbe_tp_switch_gears.C new file mode 100644 index 0000000..dc9cb47 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_switch_gears.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_switch_gears.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_switch_gears.C +/// +/// @brief SBE switch gears Procedure +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_sbe_tp_switch_gears.H" +fapi2::ReturnCode p9_sbe_tp_switch_gears(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_sbe_tp_switch_gears: Entering ..."); + + FAPI_DBG("p9_sbe_tp_switch_gears: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_sbe_tp_switch_gears.H b/src/ppe/hwp/perv/p9_sbe_tp_switch_gears.H new file mode 100644 index 0000000..3a7e893 --- /dev/null +++ b/src/ppe/hwp/perv/p9_sbe_tp_switch_gears.H @@ -0,0 +1,61 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_sbe_tp_switch_gears.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_sbe_tp_switch_gears.H +/// +/// @brief SBE switch gears Procedure +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SBE_TP_SWITCH_GEARS_H_ +#define _P9_SBE_TP_SWITCH_GEARS_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_sbe_tp_switch_gears_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief -- Calls the gear switcher procedure from PIBMEM +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_sbe_tp_switch_gears(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_select_boot_master.C b/src/ppe/hwp/perv/p9_select_boot_master.C new file mode 100644 index 0000000..b849a4f --- /dev/null +++ b/src/ppe/hwp/perv/p9_select_boot_master.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_select_boot_master.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_select_boot_master.C +/// +/// @brief Select Boot Master +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_select_boot_master.H" +fapi2::ReturnCode p9_select_boot_master(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_select_boot_master: Entering ..."); + + FAPI_DBG("p9_select_boot_master: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_select_boot_master.H b/src/ppe/hwp/perv/p9_select_boot_master.H new file mode 100644 index 0000000..201fec0 --- /dev/null +++ b/src/ppe/hwp/perv/p9_select_boot_master.H @@ -0,0 +1,61 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_select_boot_master.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_select_boot_master.H +/// +/// @brief Select Boot Master +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SELECT_BOOT_MASTER_H_ +#define _P9_SELECT_BOOT_MASTER_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_select_boot_master_FP_t)( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief --Select Master Chip +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_select_boot_master(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_select_clock_mux.C b/src/ppe/hwp/perv/p9_select_clock_mux.C new file mode 100644 index 0000000..c6482cf --- /dev/null +++ b/src/ppe/hwp/perv/p9_select_clock_mux.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_select_clock_mux.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_select_clock_mux.C +/// +/// @brief proc select clock mux +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_select_clock_mux.H" +fapi2::ReturnCode p9_select_clock_mux(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_select_clock_mux: Entering ..."); + + FAPI_DBG("p9_select_clock_mux: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_select_clock_mux.H b/src/ppe/hwp/perv/p9_select_clock_mux.H new file mode 100644 index 0000000..94fa7e1 --- /dev/null +++ b/src/ppe/hwp/perv/p9_select_clock_mux.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_select_clock_mux.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_select_clock_mux.H +/// +/// @brief proc select clock mux +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SELECT_CLOCK_MUX_H_ +#define _P9_SELECT_CLOCK_MUX_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_select_clock_mux_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief Select internal clock mux to drive the memory clocks off of +/// Flips all bits needed for clock routing (processor only), centaur is done later in p9_cen_ref_clk_enable +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_select_clock_mux(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_set_fsi_gp_shadow.C b/src/ppe/hwp/perv/p9_set_fsi_gp_shadow.C new file mode 100644 index 0000000..ff32cc0 --- /dev/null +++ b/src/ppe/hwp/perv/p9_set_fsi_gp_shadow.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_set_fsi_gp_shadow.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_set_fsi_gp_shadow.C +/// +/// @brief --IPL step 0.8 proc_prep_ipl +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_set_fsi_gp_shadow.H" +fapi2::ReturnCode p9_set_fsi_gp_shadow(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_set_fsi_gp_shadow: Entering ..."); + + FAPI_DBG("p9_set_fsi_gp_shadow: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_set_fsi_gp_shadow.H b/src/ppe/hwp/perv/p9_set_fsi_gp_shadow.H new file mode 100644 index 0000000..c08c3f3 --- /dev/null +++ b/src/ppe/hwp/perv/p9_set_fsi_gp_shadow.H @@ -0,0 +1,61 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_set_fsi_gp_shadow.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_set_fsi_gp_shadow.H +/// +/// @brief --IPL step 0.8 proc_prep_ipl +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SET_FSI_GP_SHADOW_H_ +#define _P9_SET_FSI_GP_SHADOW_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_set_fsi_gp_shadow_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief --update ROOT CTRL shadows if needed +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_set_fsi_gp_shadow(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_setup_clock_term.C b/src/ppe/hwp/perv/p9_setup_clock_term.C new file mode 100644 index 0000000..0a62a24 --- /dev/null +++ b/src/ppe/hwp/perv/p9_setup_clock_term.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_setup_clock_term.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_setup_clock_term.C +/// +/// @brief proc setup clock term +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_setup_clock_term.H" +fapi2::ReturnCode p9_setup_clock_term(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_setup_clock_term: Entering ..."); + + FAPI_DBG("p9_setup_clock_term: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_setup_clock_term.H b/src/ppe/hwp/perv/p9_setup_clock_term.H new file mode 100644 index 0000000..f49bb74 --- /dev/null +++ b/src/ppe/hwp/perv/p9_setup_clock_term.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_setup_clock_term.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_setup_clock_term.H +/// +/// @brief proc setup clock term +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SETUP_CLOCK_TERM_H_ +#define _P9_SETUP_CLOCK_TERM_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_setup_clock_term_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief Setup the clock termination correctly for system/chip type +/// Since this is the first procedure run against the chips it also clears the GP write protect +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_setup_clock_term(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_setup_sbe_config.C b/src/ppe/hwp/perv/p9_setup_sbe_config.C new file mode 100644 index 0000000..68b0446 --- /dev/null +++ b/src/ppe/hwp/perv/p9_setup_sbe_config.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_setup_sbe_config.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_setup_sbe_config.C +/// +/// @brief proc setup sbe config +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_setup_sbe_config.H" +fapi2::ReturnCode p9_setup_sbe_config(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip) +{ + FAPI_DBG("p9_setup_sbe_config: Entering ..."); + + FAPI_DBG("p9_setup_sbe_config: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_setup_sbe_config.H b/src/ppe/hwp/perv/p9_setup_sbe_config.H new file mode 100644 index 0000000..5c4521b --- /dev/null +++ b/src/ppe/hwp/perv/p9_setup_sbe_config.H @@ -0,0 +1,61 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_setup_sbe_config.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_setup_sbe_config.H +/// +/// @brief proc setup sbe config +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_SETUP_SBE_CONFIG_H_ +#define _P9_SETUP_SBE_CONFIG_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_setup_sbe_config_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief update mailbox with boot parameters +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_setup_sbe_config(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/p9_start_cbs.C b/src/ppe/hwp/perv/p9_start_cbs.C new file mode 100644 index 0000000..fdec2cc --- /dev/null +++ b/src/ppe/hwp/perv/p9_start_cbs.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_start_cbs.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_start_cbs.C +/// +/// @brief Start CBS : Trigger CBS +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +//## auto_generated +#include "p9_start_cbs.H" +fapi2::ReturnCode p9_start_cbs(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> + & i_target_chip) +{ + FAPI_DBG("p9_start_cbs: Entering ..."); + + FAPI_DBG("p9_start_cbs: Exiting ..."); + + return fapi2::FAPI2_RC_SUCCESS; + +} diff --git a/src/ppe/hwp/perv/p9_start_cbs.H b/src/ppe/hwp/perv/p9_start_cbs.H new file mode 100644 index 0000000..7e89907 --- /dev/null +++ b/src/ppe/hwp/perv/p9_start_cbs.H @@ -0,0 +1,65 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwp/perv/p9_start_cbs.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//------------------------------------------------------------------------------ +/// @file p9_start_cbs.H +/// +/// @brief Start CBS : Trigger CBS +// *! +// *! OWNER NAME : Abhishek Agarwal Email: abagarw8@in.ibm.com +// *! BACKUP NAME : Email: +//------------------------------------------------------------------------------ +// *HWP HWP Owner : Abhishek Agarwal <abagarw8@in.ibm.com> +// *HWP FW Owner : Brian Silver <bsilver@us.ibm.com> +// *HWP Team : Perv +// *HWP Level : 1 +// *HWP Consumed by : SBE +//------------------------------------------------------------------------------ + + +#ifndef _P9_START_CBS_H_ +#define _P9_START_CBS_H_ + + +#include <fapi2.H> + + +typedef fapi2::ReturnCode (*p9_start_cbs_FP_t)(const + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> &); + +/// @brief --check/wait for VDN_PGOOD = 1 +/// --check for OSC ok +/// --check for VDD (VDD status check) +/// --start CBS(CBS runs thru default path) +/// +/// +/// @param[in] i_target_chip Reference to TARGET_TYPE_PROC_CHIP target +/// @return FAPI2_RC_SUCCESS if success, else error code. +extern "C" +{ + fapi2::ReturnCode p9_start_cbs(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> + & i_target_chip); +} + +#endif diff --git a/src/ppe/hwp/perv/pervasive_attributes.xml b/src/ppe/hwp/perv/pervasive_attributes.xml new file mode 100644 index 0000000..f49ed7a --- /dev/null +++ b/src/ppe/hwp/perv/pervasive_attributes.xml @@ -0,0 +1,149 @@ +<!-- IBM_PROLOG_BEGIN_TAG --> +<!-- This is an automatically generated prolog. --> +<!-- --> +<!-- $Source: src/ppe/hwp/perv/pervasive_attributes.xml $ --> +<!-- --> +<!-- OpenPOWER OnChipController Project --> +<!-- --> +<!-- Contributors Listed Below - COPYRIGHT 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 --> +<!-- This is an automatically generated file. --> +<!-- File: pervasive_attributes.xml. --> +<!-- XML file specifying attributes used by HW Procedures. Attributes are taken from model pervasive --> +<!--pervasive_attributes.xml--> +<attributes> +<attribute> + <id>ATTR_BOOT_FREQ</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_CHIP_REGIONS_TO_ENABLE</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint32</valueType> +</attribute> + +<attribute> + <id>ATTR_CHIP_UNIT_POS</id> + <targetType>TARGET_TYPE_PERV,TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_ECID</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint64</valueType> +</attribute> + +<attribute> + <id>ATTR_EC_GARD</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_EQ_GARD</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_I2C_BUS_DIV_NEST</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_I2C_BUS_DIV_REF</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_MC_SYNC_MODE</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_NEST_PLL_BUCKET</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_PROC_PB_BNDY_DMIPLL_DATA</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_PROC_PB_BNDY_DMIPLL_FOR_DCCAL_DATA</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_PROC_PERV_BNDY_PLL_DATA</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_SBE_SEEPROM_I2C_DEVICE_ADDRESS</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint32</valueType> +</attribute> + +<attribute> + <id>ATTR_SBE_SEEPROM_I2C_PORT</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint32</valueType> +</attribute> + +<attribute> + <id>ATTR_VCS_BOOT_VOLTAGE</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +<attribute> + <id>ATTR_VDD_BOOT_VOLTAGE</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description></description> + <valueType>uint8</valueType> +</attribute> + +</attributes> diff --git a/src/ppe/hwp/perv/pervfiles.mk b/src/ppe/hwp/perv/pervfiles.mk new file mode 100644 index 0000000..c99113c --- /dev/null +++ b/src/ppe/hwp/perv/pervfiles.mk @@ -0,0 +1,74 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/hwp/perv/pervfiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file pervfiles.mk +# +# @brief mk for including perv object files +# +# @page ChangeLogs Change Logs +# @section pervfiles.mk +# @verbatim +# +# @endverbatim +# +########################################################################## +# Object Files +########################################################################## + +PERV-CPP-SOURCES = p9_sbe_setup_evid.C +PERV-CPP-SOURCES +=p9_sbe_attr_setup.C +PERV-CPP-SOURCES +=p9_sbe_tp_chiplet_init1.C +PERV-CPP-SOURCES +=p9_sbe_check_master.C +PERV-CPP-SOURCES +=p9_sbe_tp_chiplet_init2.C +PERV-CPP-SOURCES +=p9_sbe_enable_seeprom.C +PERV-CPP-SOURCES +=p9_sbe_tp_chiplet_init3.C +PERV-CPP-SOURCES +=p9_sbe_lpc_init.C +PERV-CPP-SOURCES +=p9_sbe_tp_chiplet_reset.C +PERV-CPP-SOURCES +=p9_sbe_nest_arrayinit.C +PERV-CPP-SOURCES +=p9_sbe_tp_gptr_time_repr_initf.C +PERV-CPP-SOURCES +=p9_sbe_nest_chiplet_init.C +PERV-CPP-SOURCES +=p9_sbe_tp_initf.C +PERV-CPP-SOURCES +=p9_sbe_nest_chiplet_reset.C +PERV-CPP-SOURCES +=p9_sbe_tp_ld_image.C +PERV-CPP-SOURCES +=p9_sbe_nest_gptr_time_repr_initf.C +PERV-CPP-SOURCES +=p9_sbe_tp_switch_gears.C +PERV-CPP-SOURCES +=p9_sbe_nest_initf.C +PERV-CPP-SOURCES +=p9_select_boot_master.C +PERV-CPP-SOURCES +=p9_sbe_nest_startclocks.C +PERV-CPP-SOURCES +=p9_select_clock_mux.C +PERV-CPP-SOURCES +=p9_sbe_npll_initf.C +PERV-CPP-SOURCES +=p9_set_fsi_gp_shadow.C +PERV-CPP-SOURCES +=p9_sbe_npll_setup.C +PERV-CPP-SOURCES +=p9_setup_clock_term.C +PERV-CPP-SOURCES +=p9_sbe_select_ex.C +PERV-CPP-SOURCES +=p9_setup_sbe_config.C +PERV-CPP-SOURCES +=p9_sbe_tp_arrayinit.C +PERV-CPP-SOURCES +=p9_start_cbs.C + +PERV-C-SOURCES = +PERV-S-SOURCES = + +PERV_OBJECTS += $(PERV-CPP-SOURCES:.C=.o) +PERV_OBJECTS += $(PERV-C-SOURCES:.c=.o) +PERV_OBJECTS += $(PERV-S-SOURCES:.S=.o) diff --git a/src/ppe/hwp/utils/.empty b/src/ppe/hwp/utils/.empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/hwp/utils/.empty diff --git a/src/ppe/hwpf/fapi/.empty b/src/ppe/hwpf/fapi/.empty new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/hwpf/fapi/.empty diff --git a/src/ppe/hwpf/fapi/docs/Doxyfile b/src/ppe/hwpf/fapi/docs/Doxyfile new file mode 100755 index 0000000..9cb5dc4 --- /dev/null +++ b/src/ppe/hwpf/fapi/docs/Doxyfile @@ -0,0 +1,2355 @@ +# Doxyfile 1.8.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "FAPI 2" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = genfiles + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = NO + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if <section_label> ... \endif and \cond <section_label> +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = ../include ./topics + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.as \ + *.js \ + *.H + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# <filter> <input-file> +# +# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = README.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 1 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use <access key> + S +# (what the <access key> is depends on the OS and browser, but it is typically +# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down +# key> to jump into the search results window, the results can be navigated +# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel +# the search. The filter options can be selected when the cursor is inside the +# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys> +# to select a filter and <Enter> or <escape> to activate or cancel the filter +# option. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. There +# are two flavours of web server based searching depending on the +# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for +# searching and an index file used by the script. When EXTERNAL_SEARCH is +# enabled the indexing and searching needs to be provided by external tools. See +# the section "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain the +# search results. +# +# Doxygen ships with an example indexer ( doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: http://xapian.org/). +# +# See the section "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will return the search results when EXTERNAL_SEARCH is enabled. +# +# Doxygen ships with an example indexer ( doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: http://xapian.org/). See the section "External Indexing and +# Searching" for details. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. +# The default file is: searchdata.xml. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of +# to a relative location where the documentation can be found. The format is: +# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output. +# The default value is: YES. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. +# +# Note that when enabling USE_PDFLATEX this option is only used for generating +# bitmaps for formulas in the HTML output, but not in the Makefile that is +# written to the output directory. +# The default file is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate +# index for LaTeX. +# The default file is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used by the +# printer. +# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x +# 14 inches) and executive (7.25 x 10.5 inches). +# The default value is: a4. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names +# that should be included in the LaTeX output. To get the times font for +# instance you can specify +# EXTRA_PACKAGES=times +# If left blank no extra packages will be included. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the +# generated LaTeX document. The header should contain everything until the first +# chapter. If it is left blank doxygen will generate a standard header. See +# section "Doxygen usage" for information on how to let doxygen write the +# default header to a separate file. +# +# Note: Only use a user-defined header if you know what you are doing! The +# following commands have a special meaning inside the header: $title, +# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will +# replace them by respectively the title of the page, the current date and time, +# only the current date, the version number of doxygen, the project name (see +# PROJECT_NAME), or the project number (see PROJECT_NUMBER). +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the +# generated LaTeX document. The footer should contain everything after the last +# chapter. If it is left blank doxygen will generate a standard footer. +# +# Note: Only use a user-defined footer if you know what you are doing! +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_FOOTER = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the LATEX_OUTPUT output +# directory. Note that the files will be copied as-is; there are no commands or +# markers available. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is +# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will +# contain links (just like the HTML output) instead of page references. This +# makes the output suitable for online browsing using a PDF viewer. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PDF_HYPERLINKS = YES + +# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate +# the PDF file directly from the LaTeX files. Set this option to YES to get a +# higher quality PDF documentation. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode +# command to the generated LaTeX files. This will instruct LaTeX to keep running +# if errors occur, instead of asking the user for help. This option is also used +# when generating formulas in HTML. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BATCHMODE = NO + +# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the +# index chapters (such as File Index, Compound Index, etc.) in the output. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HIDE_INDICES = NO + +# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source +# code with syntax highlighting in the LaTeX output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. See +# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# The default value is: plain. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The +# RTF output is optimized for Word 97 and may not look too pretty with other RTF +# readers/editors. +# The default value is: NO. + +GENERATE_RTF = YES + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: rtf. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will +# contain hyperlink fields. The RTF file will contain links (just like the HTML +# output) instead of page references. This makes the output suitable for online +# browsing using Word or some other Word compatible readers that support those +# fields. +# +# Note: WordPad (write) and others do not support links. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's config +# file, i.e. a series of assignments. You only have to provide replacements, +# missing definitions are set to their default value. +# +# See also section "Doxygen usage" for information on how to generate the +# default style sheet that doxygen normally uses. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an RTF document. Syntax is +# similar to doxygen's config file. A template extensions file can be generated +# using doxygen -e rtf extensionFile. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for +# classes and files. +# The default value is: NO. + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. A directory man3 will be created inside the directory specified by +# MAN_OUTPUT. +# The default directory is: man. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to the generated +# man pages. In case the manual section does not start with a number, the number +# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is +# optional. +# The default value is: .3. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it +# will generate one additional man file for each entity documented in the real +# man page(s). These additional files only source the real man page, but without +# them the man command would be unable to find the correct page. +# The default value is: NO. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that +# captures the structure of the code including all documentation. +# The default value is: NO. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: xml. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a +# validating XML parser to check the syntax of the XML files. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify a XML DTD, which can be used by a +# validating XML parser to check the syntax of the XML files. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program +# listings (including syntax highlighting and cross-referencing information) to +# the XML output. Note that enabling this will significantly increase the size +# of the XML output. +# The default value is: YES. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files +# that can be used to generate PDF. +# The default value is: NO. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. +# The default directory is: docbook. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_OUTPUT = docbook + +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen +# Definitions (see http://autogen.sf.net) file that captures the structure of +# the code including all documentation. Note that this feature is still +# experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module +# file that captures the structure of the code including all documentation. +# +# Note that this feature is still experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary +# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI +# output from the Perl module output. +# The default value is: NO. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely +# formatted so it can be parsed by a human reader. This is useful if you want to +# understand what is going on. On the other hand, if this tag is set to NO the +# size of the Perl module output will be much smaller and Perl will parse it +# just the same. +# The default value is: YES. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file are +# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful +# so different doxyrules.make files included by the same Makefile don't +# overwrite each other's variables. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all +# C-preprocessor directives found in the sources and include files. +# The default value is: YES. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names +# in the source code. If set to NO only conditional compilation will be +# performed. Macro expansion can be done in a controlled way by setting +# EXPAND_ONLY_PREDEF to YES. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then +# the macro expansion is limited to the macros specified with the PREDEFINED and +# EXPAND_AS_DEFINED tags. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES the includes files in the +# INCLUDE_PATH will be searched if a #include is found. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by the +# preprocessor. +# This tag requires that the tag SEARCH_INCLUDES is set to YES. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will be +# used. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that are +# defined before the preprocessor is started (similar to the -D option of e.g. +# gcc). The argument of the tag is a list of macros of the form: name or +# name=definition (no spaces). If the definition and the "=" are omitted, "=1" +# is assumed. To prevent a macro definition from being undefined via #undef or +# recursively expanded use the := operator instead of the = operator. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +PREDEFINED = DOXYGEN + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this +# tag can be used to specify a list of macro names that should be expanded. The +# macro definition that is found in the sources will be used. Use the PREDEFINED +# tag if you want to use a different macro definition that overrules the +# definition found in the source code. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will +# remove all refrences to function-like macros that are alone on a line, have an +# all uppercase name, and do not end with a semicolon. Such function macros are +# typically used for boiler-plate code, and will confuse the parser if not +# removed. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tag files. For each tag +# file the location of the external documentation should be added. The format of +# a tag file without this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where loc1 and loc2 can be relative or absolute paths or URLs. See the +# section "Linking to external documentation" for more information about the use +# of tag files. +# Note: Each tag file must have an unique name (where the name does NOT include +# the path). If a tag file is not located in the directory in which doxygen is +# run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create a +# tag file that is based on the input files it reads. See section "Linking to +# external documentation" for more information about the usage of tag files. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external class will be listed in the +# class index. If set to NO only the inherited external classes will be listed. +# The default value is: NO. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in +# the modules index. If set to NO, only the current project's groups will be +# listed. +# The default value is: YES. + +EXTERNAL_GROUPS = YES + +# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in +# the related pages index. If set to NO, only the current project's pages will +# be listed. +# The default value is: YES. + +EXTERNAL_PAGES = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of 'which perl'). +# The default file (with absolute path) is: /usr/bin/perl. + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram +# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to +# NO turns the diagrams off. Note that this option also works with HAVE_DOT +# disabled, but it is recommended to install and use dot, since it yields more +# powerful graphs. +# The default value is: YES. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see: +# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. + +DIA_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide inheritance +# and usage relations if the target is undocumented or is not a class. +# The default value is: YES. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz (see: +# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# Bell Labs. The other options in this section have no effect if this option is +# set to NO +# The default value is: NO. + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed +# to run in parallel. When set to 0 doxygen will base this on the number of +# processors available in the system. You can set it explicitly to a value +# larger than 0 to get control over the balance between CPU load and processing +# speed. +# Minimum value: 0, maximum value: 32, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NUM_THREADS = 0 + +# When you want a differently looking font n the dot files that doxygen +# generates you can specify the font name using DOT_FONTNAME. You need to make +# sure dot is able to find the font, which can be done by putting it in a +# standard location or by setting the DOTFONTPATH environment variable or by +# setting DOT_FONTPATH to the directory containing the font. +# The default value is: Helvetica. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of +# dot graphs. +# Minimum value: 4, maximum value: 24, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the default font as specified with +# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set +# the path where dot can find it using this tag. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTPATH = + +# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for +# each documented class showing the direct and indirect inheritance relations. +# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a +# graph for each documented class showing the direct and indirect implementation +# dependencies (inheritance, containment, and class references variables) of the +# class with other documented classes. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for +# groups, showing the direct groups dependencies. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside the +# class node. If there are many fields or methods and many nodes the graph may +# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the +# number of items for each type to make the size more manageable. Set this to 0 +# for no limit. Note that the threshold may be exceeded by 50% before the limit +# is enforced. So when you set the threshold to 10, up to 15 fields may appear, +# but if the number exceeds 15, the total amount of fields shown is limited to +# 10. +# Minimum value: 0, maximum value: 100, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LIMIT_NUM_FIELDS = 10 + +# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and +# collaboration graphs will show the relations between templates and their +# instances. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +TEMPLATE_RELATIONS = NO + +# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to +# YES then doxygen will generate a graph for each documented file showing the +# direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDE_GRAPH = YES + +# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are +# set to YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH tag is set to YES then doxygen will generate a call +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical +# hierarchy of all classes instead of a textual one. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the +# dependencies a directory has on other directories in a graphical way. The +# dependency relations are determined by the #include relations between the +# files in the directories. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. +# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order +# to make the SVG files visible in IE 9+ (other browsers do not have this +# requirement). +# Possible values are: png, jpg, gif and svg. +# The default value is: png. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# +# Note that this requires a modern browser other than Internet Explorer. Tested +# and working are Firefox, Chrome, Safari, and Opera. +# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make +# the SVG files visible. Older versions of IE do not have SVG support. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +INTERACTIVE_SVG = NO + +# The DOT_PATH tag can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the \dotfile +# command). +# This tag requires that the tag HAVE_DOT is set to YES. + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = + +# The DIAFILE_DIRS tag can be used to specify one or more directories that +# contain dia files that are included in the documentation (see the \diafile +# command). + +DIAFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes +# that will be shown in the graph. If the number of nodes in a graph becomes +# larger than this value, doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that doxygen if the number of direct +# children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that +# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. +# Minimum value: 0, maximum value: 10000, default value: 50. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs +# generated by dot. A depth value of 3 means that only nodes reachable from the +# root by following a path via at most 3 edges will be shown. Nodes that lay +# further from the root node will be omitted. Note that setting this option to 1 +# or 2 may greatly reduce the computation time needed for large code bases. Also +# note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. +# Minimum value: 0, maximum value: 1000, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not seem +# to support this out of the box. +# +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) support +# this, this feature is disabled by default. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page +# explaining the meaning of the various boxes and arrows in the dot generated +# graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot +# files that are used to generate the various graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_CLEANUP = YES diff --git a/src/ppe/hwpf/fapi/docs/README b/src/ppe/hwpf/fapi/docs/README new file mode 100755 index 0000000..da66d67 --- /dev/null +++ b/src/ppe/hwpf/fapi/docs/README @@ -0,0 +1,6 @@ + +To generate FAPI2 documentation, run + +$doxygen Doxyfile + +The documentation will be output into genfiles. diff --git a/src/ppe/hwpf/fapi/docs/topics/DEPRECATED.md b/src/ppe/hwpf/fapi/docs/topics/DEPRECATED.md new file mode 100755 index 0000000..39df626 --- /dev/null +++ b/src/ppe/hwpf/fapi/docs/topics/DEPRECATED.md @@ -0,0 +1,81 @@ +@deprecated Functions which were either not found used in the +hostboot code or have other ways to perform the same operation +with the new buffers are candidates for deprecation. They are listed +here so if you're looking for something you might find that it's +deprecated and not been implemented. If there's something in this +list which should be implemented, let someone know and we can +implement it.<br> +- setDoubleWordLength(uint32_t i_newNumDoubleWords);<br> +- setWordLength(uint32_t i_newNumWords);<br> +- setHalfWordLength(uint32_t i_newNumHalfWords);<br> +- setByteLength(uint32_t i_newNumBytes);<br> +- setBitLength(uint32_t i_newNumBits);<br> +- setCapacity (uint32_t i_newNumWords);<br> +- shrinkBitLength(uint32_t i_newNumBits);<br> +- growBitLength(uint32_t i_newNumBits);<br> +Replaced with std::container operations +- shiftRight(uint32_t i_shiftnum, uint32_t i_offset = 0);<br> +Replaced with operator>> as offset appears unused<br> +- shiftLeft(uint32_t i_shiftnum, uint32_t i_offset = 0xFFFFFFFF);<br> +Replaced with operator<< as offset appears unused<br> +- shiftRightAndResize(uint32_t i_shiftnum, uint32_t i_offset = 0);<br> +- shiftLeftAndResize(uint32_t i_shiftnum);<br> +- rotateRight(uint32_t i_rotatenum);<br> +- rotateLeft(uint32_t i_rotatenum);<br> +- flushTo0(); and flushTo1();<br> +Replaced with flush<X>() where X can be {0,1}<br> +- applyInversionMask(const uint32_t * i_invMask, uint32_t + i_invByteLen);<br> +- applyInversionMask(const ecmdDataBufferBase & i_invMaskBuffer, + uint32_t i_invByteLen);<br> +- insert(const ecmdDataBufferBase & i_bufferIn, uint32_t i_targetStart, + uint32_t i_len, uint32_t i_sourceStart = 0);<br> + insert(const uint32_t * i_data, uint32_t i_targetStart, uint32_t + i_len, uint32_t i_sourceStart = 0);<br> +It appears from the usage that the insert functions were used like a +initializer list - given a chunk of data, insert at bit 0. +Other useages have been replaced with a templated version for +variable_buffers and bit operations for integral buffers.<br> +- insertFromRight<br> +Replaced with a templated version for +variable_buffers and bit operations for integral buffers.<br> +- extract API<br> +Replaced with a templated version for +variable_buffers and bit operations for integral buffers.<br> +- setOr API/merge API<br> +- concat( ... );<br> +Replaced with operator+() and operator+=()<br> +- setOr(const uint32_t * i_data, uint32_t i_startbit, + uint32_t i_len);<br> + merge() +Replaced with operator|=() as it looks like startbit is always 0 +and len is always the length of i_data. Merge is the same I think<br> +- setXor(const ecmdDataBufferBase & i_bufferIn, uint32_t i_startbit, + uint32_t i_len); +Replaced with operator|=() as it looks like startbit is always 0 +and len is always the length of i_data.<br> +- setAnd(const ecmdDataBufferBase & i_bufferIn, uint32_t i_startbit, + uint32_t i_len);<br> +Replaced with operator&=() as it looks like startbit is mostly 0 +and len is mostly the length of i_data. The few cases seen where +this isn't the case, a uint64_t mask would work better.<br> +- copy(ecmdDataBufferBase & o_copyBuffer) const +Replaced with operator=() +- memCopyIn, memCopyOut +- flattenSize(void) const; +- flatten(uint8_t * o_data, uint32_t i_len) const; +- unflatten(const uint8_t * i_data, uint32_t i_len); +- oddParity() +- evenParity() +- shareBuffer(ecmdDataBufferBase* i_sharingBuffer); +- compressBuffer(ecmdCompressionMode_t i_mode = ECMD_COMP_PRD); +- uncompressBuffer(); +- isBufferCompressed(); +- setWord(), setHalfWord(), etc. +Replaced with a templated version, set<type>(); +- getDoubleWordLength(), getDoubleLength +Replaced with a templated version taking the type as an argument +- getCapacity() +- writeBit(bits_type i_bit, uint32_t i_value); +Replaced with set operations (this might be needed?) +e
\ No newline at end of file diff --git a/src/ppe/hwpf/fapi/docs/topics/Examples.md b/src/ppe/hwpf/fapi/docs/topics/Examples.md new file mode 100755 index 0000000..e7ccb02 --- /dev/null +++ b/src/ppe/hwpf/fapi/docs/topics/Examples.md @@ -0,0 +1,246 @@ + +# Examples And Frequently Asked Questions + +## Buffers + +### Create a buffer of 32 bits and initialize it. + + fapi2::buffer<uint32_t> data(0xAA55FFAA); + +### Flip bit 0 + + data.flipBit<0>(); + +### Invert the buffer + + data.invert(); + +### Reset it's value + + data = 0xFFFFFFFF; + +### Create a mask using an anonymous object + + my_buffer &= buffer<T>().setBit<B>.invert(); + +### Create an 8 bit buffer, initialize it, and flip some bits around + + fapi2::buffer<uint8_t>(0xA5).flipBit<5>().flipBit<5>() == 0xA5; + +## Operations and Things +### Is the FAPI_TRY / 'clean_up:' method, the recommended method for doing put/getscoms? + +Yes, FAPI_TRY is the preferred wrapper for put/get scom as well as other operations which used to do the do/while/break dance based on the fapi return code. +A thread-local fapi return code, fapi2::current_err has been introduced to help with the housekeeping. + +Feel free to decompose the FAPI_TRY pattern if you have clean_up requirements which make FAPI_TRY too simplistic. + + +## Targets + +### Create a processor target + + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> A(PROCESSOR_CHIP_A); + +### Define a function which takes only a processor as an argument, enforced by the compiler + + void takesProc( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& V ); + +### How do I pass TARGET_TYPE_X into putScom? + +It should "just work." fapi2::putScom is defined as a template. +Basically any TargetType will match. So, + + Target<TARGET_TYPE_XBUS> foo; + Target<TARGET_TYPE_ABUS> bar; + +will both match fapi::putScom in it's more generic sense. However, platforms +might specialize the hw_access templates. For example, if the operation to +perform a putScom on an XBUS is different than accessing other targets, the +platform needs to specialize for XBUS. + + template<> + fapi2::ReturnCode fapi2::putScom (const fapi2::Target<TARGET_TYPE_XBUS> &i_target, const uint64_t i_address, buffer< uint64_t > &i_data) + { + // Do XBUS special code here. + } + +### How do I get <information> with the new targets when this used to be an attribute look up before? + +This question came up in the context of ATTR_CHIP_UNIT_POS, but really applies for any information +previously tucked away in attributes. + +Do the attribute lookup, the platform can optimize the look up away. In any event the get_attr macro/call will always do the right thing. + +If the platform can resolve the lookup without looking anything up (all the information is encoded in the value of the target) the attribute +mechanism can simply do that manipulation at compile time. + +For the smaller platforms, we discussed attribute look ups were templates which could be (would be?) specialized per attribute "key." +In this way, the "look up" for the unit position could be coded to be nothing more than a static manipulation of the target value. +A look up would, obviously, be needed if the unit position (or any other attribute value) couldn't be resolved from the target value alone. + +### Target Types + +#### How do I write a procedure which takes multiple target types? + +Depends on what you mean. + +##### If you mean "I have a procedure which is generic but only for a subset of types": + + fapi2::ReturnCode newProcedure( const fapi2::Target<TARGET_TYPE_XBUS | TARGET_TYPE_ABUS> & i_target, ...); + +Note that newProcedure can not then say "if xbus, do this, if abus do the +other." This is the static equivilent of grabbing a "base class" and the same +rules apply - if the method is not generic for all the subclasses, you need to +specialize for those subclasses. + +__Think twice about using this mechanism. It creates a new type (the or of the +target types) and reduces the input to this type. There is no support for run +time type conversion, and so the original type is not available in this scope.__ + +##### If you mean "I have a procedure and I want it to do different things for different target types": + +You can create templates: + + template<fapi2::TargetType T> + void newProcedure( const fapi2::Target<T>& i_target ); + + template<> + void newProcedure( const fapi2::Target<TARGET_TYPE_XBUS>& i_target ) + { + // XBUS specific code here + } + + template<> + void newProcedure( const fapi2::Target<TARGET_TYPE_ABUS>& i_target ) + { + // ABUS specific code here + } + +Notice that because the generic case for newProcedure is declared but +never defined you will get an error at compile time if newProcedure is +called with a type other than XBUS or ABUS. + +Or overloaded functions: + + void newProcedure( const fapi2::Target<TARGET_TYPE_XBUS>& i_target ) + { + // XBUS specific code here + } + + void newProcedure( const fapi2::Target<TARGET_TYPE_ABUS>& i_target ) + { + // ABUS specific code here + } + +##### If you mean "I have a procedure which is mostly generic but I need special handling for some target types": + +More or less the same as above, but define the generic template. There is no equivilent for +overloaded functions unless a composite target will suit your needs. + + template<fapi2::TargetType T> + void newProcedure( const fapi2::Target<T>& i_target ) + { + // Code for types other than ABUS or XBUS + } + + template<> + void newProcedure( const fapi2::Target<TARGET_TYPE_XBUS>& i_target ) + { + // XBUS specific code here + } + + template<> + void newProcedure( const fapi2::Target<TARGET_TYPE_ABUS>& i_target ) + { + // ABUS specific code here + } + +##### If you want to build a procedure which takes all target types: + +__It is recomended that you do not use TARGET_TYPE_ALL - that will reduce the +type of the passed in target to the "top level base class" of targets and +every procedure called will need to be completly generic. This is probably +not what you inteded (but is sometimes useful.) Rather, it is recomended +that you simply make a generic template.__ + + template<fapi2::TargetType T> + void newProcedure( const fapi2::Target<T>& i_target ) + { + // Code for all types + fapi2::putScom(i_target, ... ); + } + +Note that the putScom here will always be the correct putScom for the +target type passed in. Assuming procedures called in this method have +been specialized for specific target types, the compiler will find the +best match and call it. + +#### Once I'm in newProcedure, what is the type of the target? + +If you used a generic or specialized template, the type will be the type +of the target passed in. If you used a composite type (or'd together target +types) then the type will be TYPE_A | TYPE_B. + +Notice there's no simple way to know the original type was TYPE_A in this +case. If you think about this, it makes sense. Consider: + + void f(double x); + + int y = 3; + f(y); + +There's no way in f() to know that x started life as an int, which happened to +be cast to a double. + +Targets are the same thing - they're just types we create on the fly. So all of +the usual C++ tools to deal with this are available. + +#### So, wait - I can't write a procedure which handles multiple target types? + +You can. What you can't do is figure out the type of the object prior to +the cast. So what you need to do is make sure the original type isn't lost, +and that means you can't use TYPE_A | TYPE_B: + +##### Specialize. This is the prefered mechanism. +The template and overload examples above show how to do this specialization. +It will create very regular and easy to maintain code. + +##### Create a generic template and handle each type yourself. + + template<fapi2::TargetType T> + void newProcedure( fapi2::Target<T> i_target ) + { + // If this procedure isn't generic, check for allowed types here. + static_assert(fapi2::is_same<T, fapi2::TARGET_TYPE_ABUS>() || fapi2::is_same<T, fapi2::TARGET_TYPE_XBUS>(), + "newProcedure only takes X/A busses"); + + : + : + + if (fapi2::is_same<T, fapi2::TARGET_TYPE_ABUS>()) + { + // ABUS code + } + + if (fapi2::is_same<T, fapi2::TARGET_TYPE_XBUS>()) + { + // XBUS code + } + + : + : + } + +newProcedure is a generic template, any target type will match. And, the type T of i_target is +the original value of the target - the template matched without a cast because it's generic. +However, with that generality we lost the compiler argument type checking so we replace it with +the static_assert. This happens at compile time so the compiler will complain if a target other +than an XBUS or ABUS is passed in to this procedure. To handle the special cases for the types, +fapi2::is_same is used again - and is also a compile time operation. And so when this template +matches an XBUS target, the code generated is specific to the XBUS target. + +#### Ok, so what is TARGET_TYPE_X | TARGET_TYPE_Y for then? + +Creating procedures which are generic to those types. Think of this as a base +class method. diff --git a/src/ppe/hwpf/fapi/docs/topics/Ffdc.md b/src/ppe/hwpf/fapi/docs/topics/Ffdc.md new file mode 100755 index 0000000..85d696b --- /dev/null +++ b/src/ppe/hwpf/fapi/docs/topics/Ffdc.md @@ -0,0 +1,149 @@ + +# Using the FFDC/XML Error Parsing Tools + +For FAPI2, the parseErrorInfo PERL script has changed. The main goal was to +enable FFDC generation classes/methods. This enables a named-parameter +model as well as tucking the FFDC generation into a container which can +easily be used by the FAPI_ASSERT macro. + +## Using the Tools + +parseErrorInfo.pl [--empty-ffdc-classes] [--use-variable-buffers] --output-dir=<output dir> <filename1> <filename2> ... +- This perl script will parse HWP Error XML files and creates the following files: +- hwp_return_codes.H. HwpReturnCode enumeration (HWP generated errors) +- hwp_error_info.H. Error information (used by FAPI_SET_HWP_ERROR when a HWP generates an error) +- collect_reg_ffdc.C. Function to collect register FFDC +- set_sbe_error.H. Macro to create an SBE error + +The --empty-ffdc-classes option is for platforms which don't collect FFDC. It will generate stub classes which +will allow the source to have the same code, but compile to no-ops on certain platforms. + +The --use-variable-bufers option is for platforms which support variable buffers. + +The XML input is the same format as for P8 + +## Using the Generated Classes + +Each error found in the XML files generates a class in hwp_ffdc_classes.H. +The name of the class is the same as the return code itself (lower case) +and the set methods are the same as the elements the xml described as +needing colletion. + +Take for example RC_MBVPD_INVALID_MT_DATA. Here is the XML: + + <hwpError> + <rc>RC_MBVPD_INVALID_MT_DATA</rc> + <description> + To get the proper MT data, we need a valid + dimm rank combination. + </description> + <ffdc>RANK_NUM</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + +It generates an FFDC class which looks like this (simplified): + + class rc_mbvpd_invalid_mt_data + { + public: + rc_mbvpd_invalid_mt_data( ... ) + { FAPI_ERR("To get the proper MT data, we need a valid dimm rank combination."); } + + rc_mbvpd_invalid_mt_data& set_rank_num(const T& i_value) + { <setup ffdc> } + + void execute(void) + { + FAPI_SET_HWP_ERROR(..., RC_MBVPD_INVALID_MT_DATA); + fapi2::logError( ... ); + } + }; + +To use this, for example, you may do: + + FAPI_ASSERT( foo != bar, + rc_mbvpd_invalid_mt_data().set_rank_num(l_rank), + "foo didn't equal bar" ); + +Notice the description of the error is automatically logged. + +## Buffer Support + +In FAPI, a ReturnCode had a mechanism for "containing" an error from an +ecmdDataBuffer. The API, setEcmdError(), no longer exists. fapi2::buffers +return ReturnCodes, and as such the FFDC information is added in a manner +consistent with the rest of the FFDC gathering. + +There is a new error xml file specifically for buffers called +buffer_error.xml. It will generate an FFDC class which will take a buffer +as an argument and generate the correct FFDC. + + <hwpError> + <rc>RC_FAPI2_BUFFER</rc> + <description> + fapi2 error from a buffer operation + </description> + <buffer>BUFFER</buffer> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + +And its FFDC class: + + class rc_fapi2_buffer + { + public: + rc_fapi2_buffer( ... ) + { FAPI_ERR("fapi2 error from a buffer operation"); } + + rc_fapi2_buffer& set_buffer(const fapi2::variable_buffer& i_value) + { ... } + + template< typename T > + rc_fapi2_buffer& set_buffer(const fapi2::buffer<T>& i_value) + { ... } + }; + +And it can be used: + + fapi2::buffer<uint64_t> foo; + fapi2::variable_buffer bar; + + FAPI_ASSERT( rc != FAPI2_RC_SUCCESS, + rc_fapi2_buffer().set_fapi2_buffer(foo), + "problem with buffer" ); + + FAPI_ASSERT( rc != FAPI2_RC_SUCCESS, + rc_fapi2_buffer().set_fapi2_buffer(bar), + "problem with buffer" ); + +Note the indifference to integral or variable buffers. + +## Error Log Generation + +FAPI had a function called fapiLogError() which would generate platform +errors. The pattern was to call fapiLogError() at the end of the block +which generated the FFDC. With the addition of the FFDC classes, this +is no longer needed - the class knows to create these logs for you. + +However, the severity information is needed by this logging mechanism. +It was an argument to fapiLogError(), and so it's been added to the +constructor of the FFDC class: + +rc_repair_ring_invalid_ringbuf_ptr(fapi2::errlSeverity_t i_sev, ...) + +It defaults to "unrecoverable" and so only need be set for errors +which have a different severity. That is, doing nothing will get you +and error log with unrecoverable severity - which was the default +for FAPI. + +## Known Limitations + +- Collecting register FFDC is not presently implemented. +- Calling out to hwp to collect FFDC is not presently implemented. +- The FirstFailureData class does not have a platform pointer
\ No newline at end of file diff --git a/src/ppe/hwpf/fapi/docs/topics/README.md b/src/ppe/hwpf/fapi/docs/topics/README.md new file mode 100755 index 0000000..ee7a9f0 --- /dev/null +++ b/src/ppe/hwpf/fapi/docs/topics/README.md @@ -0,0 +1,166 @@ + +# FAPI 2 and FAPI Lite definitions for targets, buffers, error handling. + +## Were are some examples? + +Examples can be found in the "Related Pages" tab. These examples are constantly +being expanded, please check back often. + +## How is the code structured? + +There is a new namespace; fapi2. This was created to prevent +the FAPI 1 code, in the fapi namespace, from colliding with the new code. + +- Most documentation can be found under the class definition. +- Documentation for FAPI_TRY/FAPI_ASSERT is in the file error_scope.H, + and doesn't have a "tab" in the HTML like the classes and the namespaces do. +- The documentation for TargeType is in the fapi namespace section. + +## What do I need to implement for my platform? + +### fapi2::buffer and fapi2::variable_buffer +There should be nothing for platforms to implement in the buffer code. +Smaller platforms which use fapi2::variable_buffer will need to +ensure they have an implementation of std::vector. Hostboot has one +which I'm sure you can steal if needed. + +### fapi2::Target and fapi2::TargetType +Target is defined as a template of <TargetType, Value> where +Value is defined per platform. Smaller platforms will want an integer +type here, say uint64_t. Larger platforms may want to change this to +a pointer to an underlying platform specific targeting object. + +The target traversing functions will need to be implemented per-platform. + +### Hardware Access (fapi2::getScom() ...) + +All of the hardware access functions are assumed to need implementation +per platform. + +Please use template specialization for target types which need special +treatment. The API documented here are generic, but they can be made +very specific for a target type or composite type. + +For example (perhaps a poor example ...) + + template< TargetType K > + ReturnCode getScom(const Target<K>& i_target, const uint64_t i_address, + buffer<uint64_t>& o_data) +can become + + template<> + ReturnCode getScom(const Target<TARGET_TYPE_DIMM>& i_target, const uint64_t i_address, + buffer<uint64_t>& o_data) +for DIMMs + +or + + template<> + ReturnCode getScom(const Target<TARGET_TYPE_XBUS | TARGET_TYPE_ABUS>& i_target, const uint64_t i_address, + buffer<uint64_t>& o_data) + +for XBUS and ABUS + +### fapi2::ReturnCode and error_scope.H + +For smaller platforms, a fapi::ReturnCode is nothing but a uint64_t. For +larger platforms fapi2::ReturnCode inherits from a (TBD) FFDC object. + +There should be nothing to do for error_scope.H + +### fapi2::FirstFailureData (FFDC (work in progress)) + +The platform specific FFDC object will need to be implemented, but the +tooling to generate the FFDC functions used in FAPI_ASSERT will be provided. + +### Attributes + +As in FAPI 1, platforms will need to implement the mechanism behind the +ATTR_GET/SET macros. + +## How to report an issue? + +Something in here is wrong - I'm sure of it. But you found it before someone +else. Please don't fire off an email into the ether; it will get lost. +Report an issue. Issues can be tracked and you can see what other issues are +taking priority over yours, etc. It's just better for everyone. + +__To report an issue use Clear Quest__ + - Tier: ip Firmware + - Reported Release: FW910 + - Subsystem: Hostboot + - Component: FAPI + +## Not sure how to do something? + +So you've read the API documentation and it's horrible. You can't figure +out how to get anything done. Could be an issue, could be you just need the +crazy engineer who specified this horrible mess to see what struggles they +created in their overzealous attempt to make things "simple." + +__Put it on the wiki__ + +You could send someone an email, and that might work out great. But if you +use the wiki you can be abrasive with your comments! Others might be able +to help or offer an opinion or become a member of the virtual posse you're +gathering to track down the crazy engineer. Good fun? You need a hobby. + +None the less, the crazy engineer should update the FAPI 2 documentation when +the best practice is worked out, or create an issue to track the change +(and add it to a test case.) + +Examples can be found in the "Related Pages" tab. + +Questions have been asked as topics on the PFD/HW for P9 community wiki. + +## Something missing? Before you report an issue ... + +Many of the API from FAPI 1 have been changed into templated functions. For +example, + + ecmdDataBuffer::getDoubleWordLength() -> fapi::buffer::getLength<uint64_t>() + ecmdDataBuffer::getWordLength() -> fapi::buffer::getLength<uint32_t>() + ecmdDataBuffer::getHalfWordLength() -> fapi::buffer::getLength<uint16_t>() + +Some API have been deprecated in favor of other API, some API have been +deprecated and are waiting for a use-case, and they'll be implemented. +A list of deprecated ecmdDataBuffer functions can be found in the +fapi::buffer_base class documentation. + +Some API have been removed/deprecated and are expected to return in a different +form once the requirements are understood. Examples of this are the compressed +fapi::buffers. While platforms may need these functions, they have been removed +from the class itself as they are not vital to the class operation. These +functions, as needed, will be replaced with utility functions which perform the +operations needed for the platform. An example is fapi::Target::toString. +It has been replaced with fapi::toString(Target, ...) which can be overloaded +to take any type, and makes a nice utility for the fapi namespace. + +Some API have plum been forgotten. You should open an issue so we can track +the implementation. + +## Where's the documentation for Attributes? + +The attribute macros are not expected to change for FAPI 2: + + l_rc = FAPI_ATTR_GET(<ID>, l_pTarget, l_val); + l_rc = FAPI_ATTR_SET(<ID>, l_pTarget, l_val); + l_rc = FAPI_ATTR_GET_PRIVILEGED(<ID>, l_pTarget, l_val); + l_rc = FAPI_ATTR_SET_PRIVILEGED(<ID>, l_pTarget, l_val); + +There is one outstanding question: + 1. whether we should/can change from a pointer to a target to a reference + to a target to save a dereference on the smaller platforms (maybe it gets + optimized out anyway?) + + Seems like the answer will be "no," but this depends on the PPE attribute + look up scheme I think. Work in Progress. + +## Where's the FFDC documentation? + +Currently scheduled for End of February, 2015. + +## Other Known Issues + +- Thread local storage is broken on gcc 4.8, and the thread_local variables in +error_scope.H will need to become pthread TLS for the time being. diff --git a/src/ppe/hwpf/fapi/include/buffer.H b/src/ppe/hwpf/fapi/include/buffer.H new file mode 100755 index 0000000..411ed53 --- /dev/null +++ b/src/ppe/hwpf/fapi/include/buffer.H @@ -0,0 +1,423 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/buffer.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file buffer.H + * @brief definitions for fapi2 variable integral buffers + */ + +#ifndef __FAPI2_INTEGRAL_BUFFER__ +#define __FAPI2_INTEGRAL_BUFFER__ + +#include <buffer_base.H> +#include <return_code.H> + +namespace fapi2 +{ + /// @brief Class representing a FAPI buffer<T> + /// @note Buffers support method chaining. So, rather than + /// this + /// @code + /// buffer<T> mask; + /// mask.setBit<B>(); + /// mask.invert(); + /// my_buffer &= mask; + /// @endcode + /// You can do + /// @code + /// my_buffer &= buffer<T>().setBit<B>.invert(); + /// @endcode + template <typename T> + class buffer : public buffer_base<T> + { + public: + /// Shortcut typedef to map to our traits class + typedef typename buffer_base<T, buffer>::bits_type bits_type; + + /// + /// @brief Integral buffer assignment constructor + /// @param[in] i_value initial value of the buffer + /// Meaningless for variable types and thus protected. + /// + inline buffer(T i_value = 0) + { + // Why not an initializer list? That would force buffer_base<T> + // to have a ctor which took a T, and I want to avoid that in + // the generic case: this makes it more clear that the two + // ctor's (integral and container) behave very differently. + // variable_buffers also have a ctor which takes a single + // numerical value, and that represents a bit count, not an + // initial value. + this->iv_data = i_value; + } + + + /// @name Bit/Word Manipulation Functions + ///@{ + + /// + /// @brief Return the length of the buffer in bits + /// @return Length in bits + /// + inline constexpr uint32_t getBitLength(void) const + { return bufferTraits<T>::bit_length(this->iv_data); } + + /// + /// @brief Return the length of the buffer in OT units + /// @return Length in OT units rounded up + /// @tparam OT the type to get the length of. For example, if one + /// wanted the length in double words, OT would be uint64_t + /// (getLength<uint64_t>().) Similarly, to get the length in words, + /// getLength<uin32_t>(). + /// + template< typename OT > + inline constexpr uint32_t getLength(void) const + { + return bufferTraits<T>::template size<OT>(this->iv_data); + } + + /// + /// @brief Templated setBit for integral types + /// @tparam B the bit number to set. + /// @return buffer& Useful for method chaining + /// @note 0 is left-most + /// @note Example: fapi2::buffer<uint64_t>().setBit<3>(); + /// + template <bits_type B> + inline buffer& setBit(void) + { + static_assert((B >= 0) && + (B < bufferTraits<T>::bits_per_unit), "failed range check"); + + // Force iv_data to be dependent on the template type to force + // its look up in the second phase + this->iv_data |= (static_cast<T>(1)) << (bufferTraits<T>::bits_per_unit - B - 1); + return *this; + } + + /// + /// @brief Clear a bit in buffer + /// @tparam B Bit in buffer to clear. + /// @return buffer& Useful for method chaining + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template< bits_type B > + inline buffer& clearBit(void) + { + static_assert((B >= 0) && + (B < bufferTraits<T>::bits_per_unit), "failed range check"); + + this->iv_data &= buffer<T>().setBit<B>().invert(); + return *this; + } + + /// + /// @brief Invert bit + /// @tparam B Bit in buffer to invert. + /// @return buffer& Useful for method chaining + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template< bits_type B > + inline buffer& flipBit(void) + { + static_assert((B >= 0) && + (B < bufferTraits<T>::bits_per_unit), "failed range check"); + + this->iv_data ^= buffer<T>().setBit<B>(); + return *this; + } + + /// + /// @brief Set a bit in the buffer + /// @param[in] i_bit the bit number to set. + /// @note 0 is left-most + /// @return FAPI2_RC_SUCCESS if OK + /// + inline fapi2::ReturnCode setBit(const bits_type& i_bit) + { + if (i_bit >= bufferTraits<T>::bits_per_unit) + { + return FAPI2_RC_INVALID_PARAMETER; + } + + // Force iv_data to be dependent on the template type to force + // its look up in the second phase + this->iv_data |= + (static_cast<T>(1)) << (bufferTraits<T>::bits_per_unit - i_bit - 1); + return FAPI2_RC_SUCCESS; + } + + /// + /// @brief Get the value of a bit in the buffer + /// @tparam B Bit in buffer to get. + /// @return true if bit is on, false if bit is off + /// + template< bits_type B > + inline bool getBit(void) const + { + return buffer<T>().setBit<B>() & this->iv_data; + } + + ///@} + + /// @name Buffer Manipulation Functions + ///@{ + + // Note: Many (all?) of these are not needed and the compiler complains + // as the cast to T yields a better operator. There are here mainly for + // documenation purposes. + + /// + /// @brief operator>>() + /// +#ifdef DOXYGEN + buffer<T>& operator>>(bits_type i_shiftnum); +#endif + + /// + /// @brief operator<<() + /// +#ifdef DOXYGEN + buffer<T>& operator<<(bits_type i_shiftnum); +#endif + + /// + /// @brief operator+() + /// +#ifdef DOXYGEN + buffer<T>& operator+(const T& rhs); +#endif + + /// + /// @brief operator+=() + /// +#ifdef DOXYGEN + buffer<T>& operator+=(const T& rhs); +#endif + + /// + /// @brief operator|=() + /// +#ifdef DOXYGEN + buffer<T>& operator|=(const T& rhs); +#endif + + /// + /// @brief operator&=() + /// +#ifdef DOXYGEN + buffer<T>& operator&=(const T& rhs); +#endif + + /// + /// @brief operator|() + /// +#ifdef DOXYGEN + buffer<T>& operator|(const T& rhs); +#endif + + /// + /// @brief operator&() + /// +#ifdef DOXYGEN + buffer<T>& operator&(const T& rhs); +#endif + + /// + /// @brief operator^=() + /// +#ifdef DOXYGEN + buffer<T>& operator^=(const T& rhs); +#endif + + /// + /// @brief operator~() + /// +#ifdef DOXYGEN + buffer<T>& operator~(const T& rhs) const; +#endif + + /// + /// @brief operator==() + /// +#ifdef DOXYGEN + bool operator==(const T& rhs) const; +#endif + + /// + /// @brief operator!=() + /// +#ifdef DOXYGEN + bool operator!=(const T& rhs) const; +#endif + + /// + /// @brief Copy part of a OT into the DataBuffer + /// @tparam TS Start bit to insert into (target start) + /// @tparam L Length of bits to insert + /// @tparam SS Start bit in source + /// @tparam OT the type of the incoming (origin) data + /// @param[in] i_datain OT value to copy into DataBuffer + /// - data is taken left aligned + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template<bits_type TS, bits_type L, bits_type SS, typename OT> + inline void insert(const OT i_datain) + { + const bits_type target_length = parameterTraits<T>::bit_length; + const bits_type source_length = parameterTraits<OT>::bit_length; + + // Error if input data don't make sense + static_assert((TS + L) <= target_length, + "insert(): (Target Start + Len) is out of bounds"); + static_assert((SS + L) <= source_length, + "insert(): (Source Start + Len) is out of bounds"); + static_assert(TS < target_length, + "insert(): Target Start is out of bounds"); + static_assert(SS < source_length, + "insert(): Source Start is out of bounds"); + + // Get mask value for Target buffer + // Note: Need "& ((T)-1) because bit shift left for Target buffer doesn't roll off + T mask =((T(~0) << (target_length - L)) & T(~0)) >> TS; + + // Calculate the equivalent position of the input Source start for the size of the Target buffer. + + // Assume OT is smaller (sizeof(T) > sizeof(OT)) + uint64_t sourceShift = abs(TS - ((target_length - source_length) + SS)); + uint64_t sourceAlign = T(i_datain) << sourceShift; + + if (sizeof(T) == sizeof(OT)) + { + sourceShift = abs(SS - TS); + sourceAlign = (SS > TS) ? ((T)i_datain) << sourceShift : ((T)i_datain) >> sourceShift; + } + + if (sizeof(T) < sizeof(OT)) + { + sourceShift = source_length - target_length; + if (SS <= sourceShift) + { + sourceShift = sourceShift + TS - SS; + sourceAlign = ((OT)i_datain) >> sourceShift; + } + + // (SS > sourceShift) + else + { + if (sourceShift > TS) + { + sourceShift = SS - sourceShift - TS; + sourceAlign = OT(i_datain) << sourceShift; + } + else + { + sourceShift = SS - sourceShift; + sourceAlign = (sourceShift < TS) ? OT(i_datain) >> sourceShift : OT(i_datain); + } + } + } + + this->iv_data = (this->iv_data & ~mask) | (sourceAlign & mask); + return; + } + + /// + /// @brief Copy in a right aligned value + /// @tparam SB Start bit to insert into + /// @tparam L Length of bits to insert + /// @tparam OT the type of the incoming (origin) data + /// @param[in] i_datain OT value to copy into DataBuffer + /// - data is taken right aligned + /// @note Data is assumed to be aligned on the word boundary of L + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template<bits_type TS, bits_type L, typename OT> + inline void insertFromRight(const OT i_datain) + { + // Error if input data don't make sense + static_assert(L < parameterTraits<OT>::bit_length, + "insertFromRight(): Len >= input buffer"); + static_assert(TS < parameterTraits<T>::bit_length, + "insertFromRight(): Target Start is out of bounds"); + static_assert((TS + L) <= parameterTraits<T>::bit_length, + "InsertFromRight(): (Target Start + Len) is out of bounds"); + + this->insert<TS, L, parameterTraits<OT>::bit_length - L>(i_datain); + return; + } + + /// + /// @brief Copy data from this buffer into an OT + /// @tparam TS Start bit to insert into (target start) + /// @tparam L Length of bits to insert + /// @tparam SS Start bit in source + /// @tparam OT the type of the outgoing (target) + /// @param[out] o_out OT to copy into - data is placed left aligned + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template<bits_type TS, bits_type L, bits_type SS, typename OT> + inline void extract(OT& o_out) + { + // Extraction is just an insert into o_out + + buffer<OT> out(o_out); + out.insert<TS, L, SS>(this->iv_data); + o_out = out; + return; + } + +#if 0 + /// + /// @brief Copy data from this buffer into an OT and right justify + /// @tparam OT the type of the outgoing data - defaults to T + /// @tparam SB Start bit to insert into - defaults to 0 + /// @tparam SS Start bit in o_out - default value is zero + /// @tparam L Length of bits to copy - defaults to sizeof(OT) * 8 + /// @param[out] o_out OT to copy into - data is placed right aligned + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// @post Data is copied from specified location to o_out, right + /// aligned. Data is only right aligned if L < sizeof(bits_type) + /// + template< typename OT = T, bits_type L = parameterTraits<OT>::bit_length, + bits_type SB = 0, bits_type SS = 0 > + void extractFromRight(OT& o_out); +#endif + ///@} + }; +}; + +#endif diff --git a/src/ppe/hwpf/fapi/include/buffer_base.H b/src/ppe/hwpf/fapi/include/buffer_base.H new file mode 100755 index 0000000..c93d770 --- /dev/null +++ b/src/ppe/hwpf/fapi/include/buffer_base.H @@ -0,0 +1,331 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/buffer_base.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file buffer_base.H + * @brief definitions for fapi2 buffer base class + */ + +#ifndef __FAPI2_BUFFER_BASE__ +#define __FAPI2_BUFFER_BASE__ + +#include <stdint.h> +#include <initializer_list> +#include <error_scope.H> +#include <buffer_parameters.H> +#include <buffer_traits.H> +#include <return_code.H> + +namespace fapi2 +{ + /// @brief Base class for buffers and variable buffers + /// @tparam T is the type of iv_data (std::vector, etc) + /// @tparam TT is the template trait, defaults to the trait for T + /// + /// Buffers can be of two styles; buffers made from an integral type and + /// buffers made from a container. Integral type buffers, while limited + /// in size, can be tightly controlled via the compiler by using c++ + /// templates. + /// + /// C++ templates allow for very explicit control, but yield a + /// syntax different than the FAPI 1.x functional interface. For example, + /// a fapi2::buffer is defined as having a type: + /// @code + /// fapi2::buffer<uint64_t> new_buffer; + /// @endcode + /// defines a buffer with exactly 64 bits, and can be manipulated by the + /// compiler as a single intrgral value. These implementations result + /// in concise instruction streams, and a platform may choose to implement + /// all or some or none of the integral buffer types. + /// + /// Buffers which have containers as their underlying implementation + /// are found in the class fapi2::variable_buffer. variable_buffer is little + /// more than + /// @code + /// fapi2::buffer<fapi2::bits_container> + /// @endcode + /// where bits_container is the typedef of the underlying container (a + /// vector of uint32_t, for example) + /// + /// Examples:<br> + /// + /// * Simple uint64_t buffer + /// @code + /// const uint32_t x = 2; + /// + /// // this data buffer will contain data in a uint64_t type + /// fapi2::buffer<uint64_t> data; + /// + /// // Set using the template and a constant + /// data.setBit<x>(); + /// + /// // Set using the template and a value + /// data.setBit<3>(); + /// + /// // Set using the function interface, and a value + /// data.setBit(1); + /// + /// // compiler gets smart. + /// // movabs $0x7000000000000000,%rsi + /// @endcode + /// + /// * variable_buffer, same thing + /// @code + /// + /// const uint32_t x = 2; + /// + /// // Note: only 15 bits long + /// fapi2::variable_buffer data(15); + /// + /// + /// data.setBit(x); + /// data.setBit(3); + /// data.setBit(1); + /// @endcode + /// + /// * method chaining + /// Buffers support method chaining. So, rather than + /// this + /// @code + /// buffer<T> mask; + /// mask.setBit<B>(); + /// mask.invert(); + /// my_buffer &= mask; + /// @endcode + /// You can do + /// @code + /// my_buffer &= buffer<T>().setBit<B>.invert(); + /// @endcode + /// + /// * buffer operations + /// @code + /// + /// // An 8 bit buffer, initialized with a value + /// fapi2::buffer<uint8_t> eight_bits = 0xAA; + /// fapi2::buffer<uint8_t> another_eight; + /// fapi2::buffer<uint16_t> sixteen_bits; + /// + /// // You can't assign an 8 bit buffer to a 16 bit buffer. + /// sixteen_bits = eight_bits; ERROR + /// + /// // But you can assign buffers of the same type + /// another_eight = eight_bits; + /// + /// // You can assign constants (or other known values) directly: + /// sixteen_bits = 0xAABB; + /// @endcode + /// + /// * Variable buffer operations + /// + /// @code + /// fapi2::variable_buffer data(16); + /// + /// // Very large buffers can be initialized rather than set bit by bit. + /// const fapi2::variable_buffer bit_settings_known( + /// {0xFFFF0000, 0xAABBF0F0, + /// 0xFFFF0000, 0xAABBF0F0, + /// 0xFFFF0000, 0xAABBF0F0,}); + /// + /// // Assignment will expand or shrink the size automatically. + /// data = bit_settings_known; + /// + /// // You can assign directly to the buffer: + /// fapi2::variable_buffer other_bits; + /// const fapi2::container_unit x = 0xFF00AA55; + /// other_bits = {x, 0xDEADBEEF}; + /// @endcode + /// + template <typename T, typename TT = bufferTraits<T> > + class buffer_base + { + + public: + + /// Shortcut typedef to get to our traits class + typedef typename TT::bits_type bits_type; + /// Shortcut typedef to get to our traits class + typedef typename TT::unit_type unit_type; + + /// + /// @brief Default constructor + /// @note iv_data will get the "default" construction, which is + /// correct - 0 for integral types, an empty container for the others. + /// + buffer_base(void): + iv_data() + {} + + virtual ~buffer_base(void) + {} + +#ifndef DOXYGEN + /// @brief Print the contents of the buffer to stdout + inline void print(void) const + { TT::print(iv_data); } +#endif + /// + /// @brief Get the contents of the buffer + /// @return The contents of the buffer + /// + inline operator T() const { return iv_data; } + + /// + /// @brief Get the contents of the buffer + /// @return The contents of the buffer + /// + inline operator T&() { return iv_data; } + + /// + /// @brief Get the contents of the buffer + /// @return The contents of the buffer + /// + inline T& operator()(void) { return iv_data; } + + /// + /// @brief Get the contents of the buffer + /// @return Reference to the contents of the buffer + /// + inline const T& operator()(void) const { return iv_data; } + + /// + /// @brief Get a pointer to the buffer bits + /// @return Pointer to the buffer itself + /// + inline T* pointer(void) { return &iv_data; } + + /// @name Buffer Manipulation Functions + ///@{ + + /// + /// @brief Set an OT of data in buffer + /// @param[in] i_value sizeof(OT) bits of data + /// @param[in] i_offset Start OT (start word, for example) in buffer + /// - defaults to 0 (will by default write the left most element) + /// @return FAPI2_RC_SUCCESS on success, FAPI2_RC_OVERFLOW otherwise + /// @note This is is only available for integral types. To set a + /// variable_buffer into a variable_buffer, use insert() + /// + template< typename OT> + inline fapi2::ReturnCode set(OT i_value, const bits_type i_offset = 0) + { + // Compile time check to make sure OT isn't a variable buffer + static_assert( !std::is_same<bits_container, OT>::value, + "Can't use a variable_buffer as input to set()" ); + + // + // There's a gotcha in here. size<OT>() returns the size in the buffer + // in OT units *rounded up*. This is the actual size of the buffer, not + // the perceived size of a variable_buffer. This should be OK however, + // as what we're trying to prevent is overflow, which this should do. + // + const uint32_t length = TT:: template size<OT>(iv_data); + static const bits_type bits_in_value = parameterTraits<OT>::bit_length; + const bits_type bit_length = TT::bit_length(iv_data); + + if (i_offset >= length) + { + return FAPI2_RC_OVERFLOW; + } + + // Create mask if part of this byte is not in the valid part of the buffer, + // Shift it left by the amount of unused bits, + // Clear the unused bits + if (((i_offset + 1) == length) && (bit_length % bits_in_value)) { + i_value &= parameterTraits<OT>::mask << ((bits_in_value * length) - bit_length); + } + + parameterTraits<OT>::template write_element<unit_type>(TT::get_address(iv_data), i_value, i_offset); + return FAPI2_RC_SUCCESS; + } + + /// + /// @brief Set and entire buffer to X's + /// @tparam X {0,1} depending if you want to clear (0) + /// or fill (1) a buffer + /// + template< uint8_t X > + inline void flush(void) + { + static_assert( (X == 1) || (X == 0), "bad argument to flush" ); + (0 == X) ? TT::clear(iv_data) : TT::set(iv_data); + } + + /// + /// @brief Invert entire buffer + /// @return buffer_base&, Useful for method chaining + /// + inline buffer_base& invert(void) + { TT::invert(iv_data); return *this; } + + /// + /// @brief Bit reverse entire buffer + /// @return buffer_base&, Useful for method chaining + /// + inline buffer_base& reverse(void) + { TT::reverse(iv_data); return *this; } + + //@} + protected: + + /// + /// @brief Variable buffer constructor + /// @param[in] i_value number of *bits* (sizeof(container_units) * 8) + /// needed. Meaningless for integral types and thus protected. + /// + buffer_base(bits_type i_value); + + /// + /// @brief Variable buffer construct from a list + /// @param[in] i_value an initializer list to initialize the container. + /// Meaningless for integral types and thus protected + /// + buffer_base(std::initializer_list<unit_type> i_value); + + /// + /// @brief Clear the buffer + /// + inline void clear(void) + { TT::clear(iv_data); } + + /// The contents of the buffer + T iv_data; + }; + + template <typename T, typename TT> + inline buffer_base<T, TT>::buffer_base(bits_type i_value): + iv_data( std::max(bits_type(1), + bits_type(i_value / 8 / sizeof(bits_type)))) + { + } + + template <typename T, typename TT> + inline buffer_base<T, TT>::buffer_base(std::initializer_list<unit_type> i_value): + iv_data(i_value) + { + } +}; + + + +#endif diff --git a/src/ppe/hwpf/fapi/include/buffer_parameters.H b/src/ppe/hwpf/fapi/include/buffer_parameters.H new file mode 100755 index 0000000..cee4531 --- /dev/null +++ b/src/ppe/hwpf/fapi/include/buffer_parameters.H @@ -0,0 +1,65 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/buffer_parameters.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file buffer_parameters.H + * @brief definitions for fapi2 buffer parameter types + */ + +#ifndef __FAPI2_BUFFER_PARAM__ +#define __FAPI2_BUFFER_PARAM__ + +#include <stdint.h> + +namespace fapi2 +{ + /// @cond + /// @brief Traits of buffer parameters - things passed in + /// @tparam T is the type of i_value (typically an integral type) + template<typename T> + class parameterTraits + { + public: + enum + { + mask = T(~0), + bit_length = sizeof(T) * 8, + byte_length = sizeof(T), + }; + + template<typename U> + inline static void write_element(void* i_data, T i_value, uint32_t i_offset) + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + T* ptr = (T*)i_data + (i_offset ^ ((sizeof(U) / sizeof(T)) - 1)); +#else + T* ptr = (T*)i_data + i_offset; +#endif + *ptr = i_value; + } + }; + /// @endcond +}; + +#endif diff --git a/src/ppe/hwpf/fapi/include/buffer_traits.H b/src/ppe/hwpf/fapi/include/buffer_traits.H new file mode 100755 index 0000000..3d5955e --- /dev/null +++ b/src/ppe/hwpf/fapi/include/buffer_traits.H @@ -0,0 +1,232 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/buffer_traits.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file buffer_traits.H + * @brief trait definitions for fapi2 buffer base class + */ + +#ifndef __FAPI2_BUFFER_TRAITS__ +#define __FAPI2_BUFFER_TRAITS__ + +#include <stdint.h> +#include <vector> +#include <algorithm> +#include <buffer_parameters.H> + +// for debug printing ... can be removed for flight +#include <iostream> +#include <iterator> + +namespace fapi2 +{ + /// @cond + /// Types representing a container of bits. Used to create + /// variable_buffer. + typedef uint32_t container_unit; + typedef std::vector<container_unit> bits_container; + + /// @brief Traits of buffers + // In general, we try to give buffers traits reflecting integral types. If + // this fails, the compiler will let someone know. + /// + /// @tparam T is the type of iv_data (std::vector, etc) + /// @tparam B is the type of the bit-specifier, typically uint32_t + template<typename T, typename B = uint32_t> + class bufferTraits + { + public: +#ifndef DOXYGEN + /// + /// @brief Print a container of bits + /// @param[in] i_data the container of bits + /// + static inline void print(const T& i_data) + { + // convert to uint64_t to prevent uint8_t from being + // printed as a char. + std::cout << "\tdata is " + << std::hex + << static_cast<uint64_t>(i_data) + << std::dec << std::endl; + } +#endif + + /// + /// @brief Return the size of the buffer in E units + /// @tparam E, the element size. + /// @param[in] io_buffer the buffer which to size + /// @return The size of the buffer in E's rounded up + /// + template<typename E> + constexpr static B size(const T& i_buffer) + { + return (bit_length(i_buffer) + + (parameterTraits<E>::bit_length - 1)) / + parameterTraits<E>::bit_length; + } + + /// + /// @brief Return the size of the buffer itself + /// @param[in] io_buffer the buffer which to size + /// @return The size of the buffer in bits (not units) + /// + constexpr static B bit_length(const T&) + { return sizeof(T) * 8; } + + /// + /// @brief Clear the buffer + /// @param[in,out] io_buffer the buffer which to clear + /// + static inline void clear(T& io_buffer) + { io_buffer = static_cast<T>(0); } + + /// + /// @brief Set the buffer + /// @param[in,out] io_buffer the buffer which to set + /// + static inline void set(T& io_buffer) + { io_buffer = static_cast<T>(~0); } + + /// + /// @brief Invert the buffer + /// @param[in,out] io_buffer the buffer which to invert + /// + static inline void invert(T& io_buffer) + { io_buffer = ~io_buffer; } + + /// + /// @brief Reverse the buffer + /// @param[in,out] io_buffer the buffer which to reverse + /// + static inline void reverse(T& io_buffer) + { + io_buffer = + ((io_buffer & 0xAAAAAAAAAAAAAAAA) >> 1) | + ((io_buffer & 0x5555555555555555) << 1); + } + + /// + /// @brief Get the address of the buffer as an array + /// @param[in] i_buffer the buffer which to invert + /// @return The address of the first element of the buffer + /// + static inline void* get_address(T& i_buffer) + { return (void*)&i_buffer; } + + typedef B bits_type; + typedef T unit_type; + enum { bits_per_unit = sizeof(unit_type) * 8 }; + }; + + // + // + /// @brief Traits for buffers which are a container of bits + // + // + template<> + class bufferTraits<bits_container, uint32_t> + { + public: +#ifndef DOXYGEN + /// + /// @brief Print a container of bits + /// @param[in] i_data the container of bits + /// + static inline void print(const bits_container& i_data) + { + std::cout << "\tdata is " << std::hex; + std::copy(i_data.begin(), i_data.end(), + std::ostream_iterator<container_unit>(std::cout, " ")); + std::cout << std::dec << std::endl; + } +#endif + + /// + /// @brief Return the size of the buffer in E units + /// @tparam E, the element size. + /// @param[in] io_buffer the buffer which to size + /// @return The size of the buffer in E's rounded up + /// + template<typename E> + constexpr static uint32_t size(const bits_container& i_buffer) + { + return (bit_length(i_buffer) + + (parameterTraits<E>::bit_length - 1)) / + parameterTraits<E>::bit_length; + } + + /// + /// @brief Return the size of the buffer itself + /// @param[in,out] io_buffer the buffer which to size + /// @return The size of the buffer in bits (not units) + /// + static inline uint32_t bit_length(const bits_container& i_buffer) + { return i_buffer.size() * sizeof(container_unit) * 8; } + + /// + /// @brief Clear the buffer + /// @param[in,out] io_buffer the buffer which to clear + /// + static inline void clear(bits_container& io_buffer) + { io_buffer.assign(io_buffer.size(), 0); } + + /// + /// @brief Set the buffer + /// @param[in,out] io_buffer the buffer which to set + /// + static inline void set(bits_container& io_buffer) + { io_buffer.assign(io_buffer.size(), ~0); } + + /// + /// @brief Invert the buffer + /// @param[in,out] io_buffer the buffer which to invert + /// + static inline void invert(bits_container& io_buffer) + { + std::transform(io_buffer.begin(), io_buffer.end(), + io_buffer.begin(), + [](container_unit u) { return ~u; }); + } + + /// + /// @brief Get the address of the buffer as an array + /// @param[in] i_buffer the buffer which to invert + /// @return The address of the first element of the buffer + /// + static inline void* get_address(bits_container& i_buffer) + { + return (void*)&(i_buffer[0]); + } + + typedef uint32_t bits_type; + typedef container_unit unit_type; + enum { bits_per_unit = sizeof(unit_type) * 8 }; + }; + /// @endcond +}; + + + +#endif diff --git a/src/ppe/hwpf/fapi/include/collect_reg_ffdc.H b/src/ppe/hwpf/fapi/include/collect_reg_ffdc.H new file mode 100755 index 0000000..661cdda --- /dev/null +++ b/src/ppe/hwpf/fapi/include/collect_reg_ffdc.H @@ -0,0 +1,80 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/collect_reg_ffdc.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/** + * @file collect_reg_ffdc.H + * + * @brief Defines the collectRegFfdc function that collects chip or + * chiplet register FFDC data. This is called automatically by + * FAPI_SET_HWP_ERROR (when a HWP creates an error) and + * FAPI_ADD_INFO_TO_HWP_ERROR (when an FFDC HWP adds error information + * to an existing error) if the error XML contains a + * <collectRegisterFfdc> element. This function should not be called + * directly by any user code. The function implementation is + * automatically generated from FAPI Error XML files. + */ + +#ifndef FAPI2_COLLECT_REG_FFDC_H_ +#define FAPI2_COLLECT_REG_FFDC_H_ + +#include <target.H> +#include <return_code.H> +#include <ffdc.H> +#include <hwp_error_info.H> + +namespace fapi2 +{ + + /// + /// @brief Collects Register FFDC from a chip or chiplet + /// + /// @warning This should only be called by FAPI during FAPI_SET_HWP_ERROR or + /// FAPI_ADD_INFO_TO_HWP_ERROR + /// + /// @param[in] i_target Pointer to Target to collect FFDC from + /// @param[in] i_ffdcId FFDC Identifier + /// @param[out] o_rc Reference to ReturnCode that FFDC is added to + /// @param[in] i_child Specifies type of i_target's chiplet to collect + /// FFDC from. If this parameter is TARGET_TYPE_NONE + /// (default value), then register FFDC is collected + /// from i_target, else, register FFDC is collected + /// from all functional child chiplets i_target of + /// the specified type + /// @param[in] i_presChild When specified, register FFDC will be collected + /// from i_target's registers based on present chiplets + /// of this type. + /// @param[in] i_childOffsetMult Specifies the chiplet position offset multiplier. + /// This is used in calculating the scom register + /// addresses when collecting register FFDC based on + /// present child chiplets. + /// + void collectRegFfdc(const fapi2::Target<TARGET_TYPE_ALL>* i_target, + const fapi2::HwpFfdcId i_ffdcId, + fapi2::ReturnCode & o_rc, + const TargetType i_child = TARGET_TYPE_NONE, + const TargetType i_presChild = TARGET_TYPE_NONE, + uint32_t i_childOffsetMult = 0); +} + +#endif diff --git a/src/ppe/hwpf/fapi/include/error_info.H b/src/ppe/hwpf/fapi/include/error_info.H new file mode 100755 index 0000000..d87aa8c --- /dev/null +++ b/src/ppe/hwpf/fapi/include/error_info.H @@ -0,0 +1,854 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/error_info.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,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 */ + +/// +/// @file error_info.H +/// @brief Defines the Error Information structures and classes +/// + +#ifndef FAPI2_ERRORINFO_H_ +#define FAPI2_ERRORINFO_H_ + +#include <stdint.h> +#include <memory> +#include <vector> +#include <target.H> +#include <assert.h> + +namespace fapi2 +{ + class ReturnCode; + + /// + /// @brief Type to hold the ffdc element in the ffdc class + /// Needed so that the size can be squirled away before the + /// macro is called. + /// + class ffdc_t + { + public: + ffdc_t(void) + {} + + operator const void*() const { return iv_value.first; } + operator const uint8_t() const + { return *(reinterpret_cast<const uint8_t*>(iv_value.first)); } + + int16_t size(void) const { return iv_value.second; } + int16_t& size(void) { return iv_value.second; } + + const void* ptr(void) const { return iv_value.first; } + const void*& ptr(void) { return iv_value.first; } + + private: + std::pair<const void*, int16_t> iv_value; + }; + + /// + /// @brief Enumeration of ErrorInfo FFDC sizes that are used to indicate a + /// special type that cannot simply be memcopied + enum ErrorInfoFfdcSize + { + EI_FFDC_SIZE_BUF = 0xffff, // fapi2::buffer<T> + EI_FFDC_SIZE_TARGET = 0xfffe, // fapi2::Target + EI_FFDC_SIZE_VBUF = 0xfffd, // fapi2::variable_buffer + EI_FFDC_MAX_SIZE = 0x1000, // Limit regular FFDC capture to 4kb + }; + + /// + /// @brief Enumeration of error log severity. + /// + enum errlSeverity_t + { + FAPI2_ERRL_SEV_RECOVERED = 0x10, /// Not seen by customer + FAPI2_ERRL_SEV_PREDICTIVE = 0x20, /// Error recovered but customer will see + FAPI2_ERRL_SEV_UNRECOVERABLE = 0x40 /// Unrecoverable, general + }; + + /// + /// @brief Enumeration of ErrorInfo types + /// + enum ErrorInfoType + { + EI_TYPE_FFDC = 0, + EI_TYPE_HW_CALLOUT = 1, + EI_TYPE_PROCEDURE_CALLOUT = 2, + EI_TYPE_BUS_CALLOUT = 3, + EI_TYPE_CDG = 4, // Target Callout/Deconfig/GARD + EI_TYPE_CHILDREN_CDG = 5, // Children Callout/Deconfig/GARD + EI_TYPE_COLLECT_TRACE = 6, + EI_LAST_TYPE = EI_TYPE_COLLECT_TRACE + 1, + }; + + /// + /// @enum HwCallout + /// + /// This enumeration defines the possible Hardware Callouts that are not + /// represented by fapi2::Targets + /// + /// Note that platform code may depend on the enum values starting at 0 and + /// incrementing in order to efficiently convert to a platform callout value + /// so do not reorder without consulting all platforms + /// + namespace HwCallouts + { + enum HwCallout + { + // Where indicated, a HW Callout in FAPI Error XML must include a + // reference target that is used to identify the HW. e.g. for + // TOD_CLOCK, the proc chip that the clock is attached to must be + // specified + TOD_CLOCK = 0, // Include proc-chip ref (or child chiplet) + MEM_REF_CLOCK = 1, // Include membuf-chip ref (or child chiplet) + PROC_REF_CLOCK = 2, // Include proc-chip ref (or child chiplet) + PCI_REF_CLOCK = 3, // Include proc-chip ref (or child chiplet) + FLASH_CONTROLLER_PART = 4, + PNOR_PART = 5, + SBE_SEEPROM_PART = 6, + VPD_PART = 7, + LPC_SLAVE_PART = 8, + GPIO_EXPANDER_PART = 9, + SPIVID_SLAVE_PART = 10, + }; + } + + /// + /// @enum ProcedureCallout + /// + /// This enumeration defines the possible Procedure Callouts + /// These instruct the customer/customer-engineer what to do + /// + /// Note that platform code may depend on the enum values starting at 0 and + /// incrementing in order to efficiently convert to a platform callout value + /// so do not reorder without consulting all platforms + /// + namespace ProcedureCallouts + { + enum ProcedureCallout + { + CODE = 0, // Code problem + LVL_SUPPORT = 1, // Call next level of support + MEMORY_PLUGGING_ERROR = 2, // DIMM Plugging error + BUS_CALLOUT = 3, // Bus Called Out + }; + } + + /// + /// @enum CalloutPriority + /// + /// This enumeration defines the possible Procedure and Target callout priorities + /// + /// Note that platform code may depend on the enum values starting at 0 and + /// incrementing in order to efficiently convert to a platform priority value + /// so do not reorder without consulting all platforms + /// + namespace CalloutPriorities + { + enum CalloutPriority + { + LOW = 0, + MEDIUM = 1, + HIGH = 2, + }; + } + + /// + /// @enum Collect Trace + /// + /// This enumeration defines the possible firmware traces to collect + /// + namespace CollectTraces + { + const uint32_t TRACE_SIZE = 256; // limit collected trace size + enum CollectTrace + { + FSI = 1, + SCOM = 2, + SCAN = 3, + MBOX = 4, + }; + } + + /// + /// @brief Get FFDC Size + /// + /// This is called by the FAPI_SET_HWP_ERROR macro to find out the size of + /// FFDC data. If the data is of a special type that is handled differently + /// than types that are simply memcopied then it is handled by a template + /// specialization. + /// If this function template is instantiated with a pointer, the compile + /// will fail. + /// + /// @return uint16_t. Size of the FFDC data + /// + template<typename T> + inline uint16_t getErrorInfoFfdcSize(const T &) + { + static_assert(sizeof(T) <= EI_FFDC_MAX_SIZE, + "FFDC too large to capture"); + return sizeof(T); + } + + /// + /// @brief Compile error if caller tries to get the FFDC size of a pointer + /// + template<typename T> + inline uint16_t getErrorInfoFfdcSize(const T*) + { + static_assert(std::is_pointer<T>::value, + "pointer passed to getErrorInfoFfdcSize"); + } + + /// + /// @brief Get FFDC Size specialization for fapi2::Target + /// + template<> + inline uint16_t getErrorInfoFfdcSize(const fapi2::Target<TARGET_TYPE_ALL>*) + { + return EI_FFDC_SIZE_TARGET; + } + + /// + /// @brief Get FFDC Size specialization for ffdc method arguments + /// @note The ffdc class sets the std::pair when the method is + /// called so the size has been calculated. All that needs to be + /// done here is to grab it. We do it this way so the macro definitions + /// can be the same whether the ffdc class is used or the old-school + /// locals. + /// + template<> + inline uint16_t getErrorInfoFfdcSize(const fapi2::ffdc_t& i_thing) + { + return i_thing.size(); + } + + /// + /// @class ErrorInfoFfdc + /// + /// This class contains a copy of some FFDC data + /// + class ErrorInfoFfdc + { + public: + /// + /// @brief Constructor + /// + /// @param[in] i_ffdcId FFDC Identifier (used to decode FFDC) + /// @param[in] i_pFfdc Pointer to the FFDC to copy + /// @param[in] i_size Size of the FFDC to copy + /// + ErrorInfoFfdc(const uint32_t i_ffdcId, + const void* i_pFfdc, + const uint32_t i_size); + + /// + /// @brief Get a pointer to the FfdcData + /// + /// @param[out] o_size Reference to uint32_t that is filled in with + /// the FFDC size + /// + /// @return void *. Pointer to the FFDC + /// + inline const void* getData(uint32_t & o_size) const + { + o_size = iv_size; + return iv_pFfdc.get(); + } + + /// + /// @brief Get a pointer to the FfdcData + /// @return void *. Pointer to the FFDC + /// + inline void* getData(void) const + { return iv_pFfdc.get(); } + + /// + /// @brief Get the FFDC Identifier + /// + /// @return uint32_t The FFDC Identifier + /// + inline uint32_t getFfdcId(void) + { return iv_ffdcId; } + +#ifdef FAPI_CUSTOM_MALLOC + /// + /// @brief Overload new operator to use platform-specific allocator + /// + /// @param[in] i_sz Size of memory to allocate in bytes + /// + /// @return Pointer to allocated memory + /// + static void* operator new(size_t i_sz); + + /// + /// @brief Overload delete operator to use platform-specific deallocator + /// + /// @param[in] i_ptr Pointer to memory previously allocated with new + /// + static void operator delete(void* i_ptr); +#endif + + private: + + // FFDC Identifier + uint32_t iv_ffdcId; + + // Pointer to the FFDC + std::shared_ptr<uint8_t> iv_pFfdc; + + // Size of the FFDC + uint32_t iv_size; + + // Disabled + ErrorInfoFfdc(const ErrorInfoFfdc &) = delete; + ErrorInfoFfdc & operator=(const ErrorInfoFfdc &) = delete; + }; + + /// + /// @struct ErrorInfoHwCallout + /// + /// This struct contains hardware to callout + /// + struct ErrorInfoHwCallout + { + /// + /// @brief Constructor. + /// + /// @param[in] i_hw Hardware to callout + /// @param[in] i_calloutPriority Priority of callout + /// @param[in] i_refTarget Reference to reference target + /// + ErrorInfoHwCallout( + const HwCallouts::HwCallout i_hw, + const CalloutPriorities::CalloutPriority i_calloutPriority, + const Target<TARGET_TYPE_ALL> & i_refTarget); + +#ifdef FAPI_CUSTOM_MALLOC + /// + /// @brief Overload new operator to use platform-specific allocator + /// + /// @param[in] i_sz Size of memory to allocate in bytes + /// + /// @return Pointer to allocated memory + /// + static void* operator new(size_t i_sz); + + /// + /// @brief Overload delete operator to use platform-specific deallocator + /// + /// @param[in] i_ptr Pointer to memory previously allocated with new + /// + static void operator delete(void* i_ptr); +#endif + + // The hw to callout + HwCallouts::HwCallout iv_hw; + + // The callout priority + CalloutPriorities::CalloutPriority iv_calloutPriority; + + // The reference target (needed for some HW callouts to identify what to + // callout). The target handle is NULL if there is no reference target. + Target<TARGET_TYPE_ALL> iv_refTarget; + }; + + /// + /// @struct ErrorInfoProcedureCallout + /// + /// This struct contains a procedure to callout + /// + struct ErrorInfoProcedureCallout + { + /// + /// @brief Constructor. + /// + /// @param[in] i_procedure Procedure to callout + /// @param[in] i_calloutPriority Priority of callout + /// + ErrorInfoProcedureCallout( + const ProcedureCallouts::ProcedureCallout i_procedure, + const CalloutPriorities::CalloutPriority i_calloutPriority); + +#ifdef FAPI_CUSTOM_MALLOC + /// + /// @brief Overload new operator to use platform-specific allocator + /// + /// @param[in] i_sz Size of memory to allocate in bytes + /// + /// @return Pointer to allocated memory + /// + static void* operator new(size_t i_sz); + + /// + /// @brief Overload delete operator to use platform-specific deallocator + /// + /// @param[in] i_ptr Pointer to memory previously allocated with new + /// + static void operator delete(void* i_ptr); +#endif + + // The procedure to callout + ProcedureCallouts::ProcedureCallout iv_procedure; + + // The callout priority + CalloutPriorities::CalloutPriority iv_calloutPriority; + }; + + /// + /// @struct ErrorInfoBusCallout + /// + /// This struct contains a bus to callout + /// + struct ErrorInfoBusCallout + { + /// + /// @brief Constructor. + /// + /// @param[in] i_target1 Reference to target on one end of the bus + /// @param[in] i_target2 Reference to target on other end of the bus + /// @param[in] i_calloutPriority Priority of callout + /// + ErrorInfoBusCallout( + const Target<TARGET_TYPE_ALL> & i_target1, + const Target<TARGET_TYPE_ALL> & i_target2, + const CalloutPriorities::CalloutPriority i_calloutPriority); + +#ifdef FAPI_CUSTOM_MALLOC + /// + /// @brief Overload new operator to use platform-specific allocator + /// + /// @param[in] i_sz Size of memory to allocate in bytes + /// + /// @return Pointer to allocated memory + /// + static void* operator new(size_t i_sz); + + /// + /// @brief Overload delete operator to use platform-specific deallocator + /// + /// @param[in] i_ptr Pointer to memory previously allocated with new + /// + static void operator delete(void* i_ptr); +#endif + + // The targets on each end of the bus to callout + Target<TARGET_TYPE_ALL> iv_target1; + Target<TARGET_TYPE_ALL> iv_target2; + + // The callout priority + CalloutPriorities::CalloutPriority iv_calloutPriority; + }; + + /// + /// @struct ErrorInfoCDG + /// + /// This struct contains a target to callout/deconfigure/GARD + /// + struct ErrorInfoCDG + { + /// + /// @brief Constructor. + /// + /// @param[in] i_target Reference to the target to c/d/g + /// @param[in] i_callout True if Target should be called out + /// @param[in] i_deconfigure True if Target should be deconfigured + /// @param[in] i_gard True if Target should be GARDed + /// @param[in] i_priority The priority of any callout + /// + ErrorInfoCDG(const Target<TARGET_TYPE_ALL> & i_target, + const bool i_callout, + const bool i_deconfigure, + const bool i_gard, + const CalloutPriorities::CalloutPriority i_priority); + +#ifdef FAPI_CUSTOM_MALLOC + /// + /// @brief Overload new operator to use platform-specific allocator + /// + /// @param[in] i_sz Size of memory to allocate in bytes + /// + /// @return Pointer to allocated memory + /// + static void* operator new(size_t i_sz); + + /// + /// @brief Overload delete operator to use platform-specific deallocator + /// + /// @param[in] i_ptr Pointer to memory previously allocated with new + /// + static void operator delete(void* i_ptr); +#endif + + // The target to callout/deconfigure/GARD + Target<TARGET_TYPE_ALL> iv_target; + + // Callout Information + bool iv_callout; + CalloutPriorities::CalloutPriority iv_calloutPriority; + + // Deconfigure Information + bool iv_deconfigure; + + // GARD Information + bool iv_gard; + }; + + /// + /// @struct ErrorInfoChildrenCDG + /// + /// This struct contains children targets to callout/deconfigure/GARD + /// + /// Children by containment can be CDG (chiplets belonging to a parent chip) + /// e.g. + /// - PROC_CHIP -> EX_CHIPLET + /// - MEMBUF_CHIP -> MBA_CHIPLET + /// Children by affinity can be CDG. + /// Any from PROC_CHIP->MCS_CHIPLET->MEMBUF_CHIP->MBA_CHIPLET->DIMM e.g. + /// - PROC_CHIP->MEMBUF_CHIP + /// - MEMBUF_CHIP->DIMM + /// - MBA_CHIPLET->DIMM + /// Port and Number criteria can be applied to the child target as + /// detailed in the constructor + /// + struct ErrorInfoChildrenCDG + { + /// + /// @brief Constructor. + /// + /// @param[in] i_parent Reference to the parent target + /// @oaram[in] i_childType Child target type to c/d/g + /// @param[in] i_callout True if Target should be called out + /// @param[in] i_deconfigure True if Target should be deconfigured + /// @param[in] i_gard True if Target should be GARDed + /// @param[in] i_priority The priority of any callout + /// @param[in] i_childPort Child Port + /// For DIMM children, the MBA port number + /// @param[in] i_childNum Child Number + /// For DIMM children, the dimm socket number + /// For Chip children, the chip position + /// For Chiplet children, the chiplet unit pos + /// + ErrorInfoChildrenCDG(const Target<TARGET_TYPE_ALL> & i_parentChip, + const TargetType i_childType, + const bool i_callout, + const bool i_deconfigure, + const bool i_gard, + const CalloutPriorities::CalloutPriority i_priority, + const uint8_t i_childPort, const uint8_t i_childNum); + +#ifdef FAPI_CUSTOM_MALLOC + /// + /// @brief Overload new operator to use platform-specific allocator + /// + /// @param[in] i_sz Size of memory to allocate in bytes + /// + /// @return Pointer to allocated memory + /// + static void* operator new(size_t i_sz); + + /// + /// @brief Overload delete operator to use platform-specific deallocator + /// + /// @param[in] i_ptr Pointer to memory previously allocated with new + /// + static void operator delete(void* i_ptr); +#endif + + // The parent chip + Target<TARGET_TYPE_ALL> iv_parent; + + // The child target types to c/d/g + TargetType iv_childType; + + // Callout Information + bool iv_callout; + CalloutPriorities::CalloutPriority iv_calloutPriority; + + // Deconfigure Information + bool iv_deconfigure; + + // GARD Information + bool iv_gard; + + // Child Port + static const uint8_t ALL_CHILD_PORTS = 0xff; + uint8_t iv_childPort; + + // Child Number + static const uint8_t ALL_CHILD_NUMBERS = 0xff; + uint8_t iv_childNumber; + }; + + /// + /// @struct ErrorInfoCollectTrace + /// + /// This struct contains trace ID to add to the error log + /// + struct ErrorInfoCollectTrace + { + /// + /// @brief Constructor. + /// + /// @param[in] i_trace + /// + ErrorInfoCollectTrace(CollectTraces::CollectTrace i_traceId); + + +#ifdef FAPI_CUSTOM_MALLOC + /// + /// @brief Overload new operator to use platform-specific allocator + /// + /// @param[in] i_sz Size of memory to allocate in bytes + /// + /// @return Pointer to allocated memory + /// + static void* operator new(size_t i_sz); + + /// + /// @brief Overload delete operator to use platform-specific deallocator + /// + /// @param[in] i_ptr Pointer to memory previously allocated with new + /// + static void operator delete(void* i_ptr); +#endif + + // trace + CollectTraces::CollectTrace iv_eiTraceId; + }; + + /// + /// @struct ErrorInfo + /// + /// This struct defines the error information associated with a fapi2::ffdc + /// Users are allowed to access the data directly + /// + struct ErrorInfo + { + +#ifdef FAPI_CUSTOM_MALLOC + /// + /// @brief Overload new operator to use platform-specific allocator + /// + /// @param[in] i_sz Size of memory to allocate in bytes + /// + /// @return Pointer to allocated memory + /// + static void* operator new(size_t i_sz); + + /// + /// @brief Overload delete operator to use platform-specific deallocator + /// + /// @param[in] i_ptr Pointer to memory previously allocated with new + /// + static void operator delete(void* i_ptr); +#endif + + // Vector of FFDC Data + std::vector<std::shared_ptr<ErrorInfoFfdc> > iv_ffdcs; + + // Vector of Hardware to callout + std::vector<std::shared_ptr<ErrorInfoHwCallout> > iv_hwCallouts; + + // Vector of procedures to callout + std::vector<std::shared_ptr<ErrorInfoProcedureCallout> > + iv_procedureCallouts; + + // Vector of buses to callout + std::vector<std::shared_ptr<ErrorInfoBusCallout> > iv_busCallouts; + + // Vector of targets to callout/deconfigure/GARD + std::vector<std::shared_ptr<ErrorInfoCDG> > iv_CDGs; + + // Vector of children targets to callout/deconfigure/GARD + std::vector<std::shared_ptr<ErrorInfoChildrenCDG> > iv_childrenCDGs; + + // Vector of traces to collect + std::vector<std::shared_ptr<ErrorInfoCollectTrace> > iv_traces; + }; + + /// + /// @brief Structure representing a single ErrorInfo entry. + /// + /// An array of these is passed to the addErrorInfo function when a HWP + /// generates an error by calling the FAPI_SET_HWP_ERROR macro + // Why aren't these inherited classes? Saves on allocation overhead. + // We create an array of ErrorInfoEntries as automatics when we start + // FFDC collection. If we did this as inherited classes it would either + // be allocating and deallocating or we'd need to allocate an array of + // the largest and map each struct in to it. That's messy to do without + // unions (that's what they're for) so we do it like this. The inherited + // model would result in a jump table anyway, so we're basically doing + // all of that by hand to avoid the mess. + // + struct ErrorInfoEntryFfdc + { + uint8_t iv_ffdcObjIndex; + uint16_t iv_ffdcSize; + uint32_t iv_ffdcId; + void addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const; + }; + + /// + /// @brief Structure representing a hardware callout + /// + struct ErrorInfoEntryHwCallout + { + uint8_t iv_hw; + uint8_t iv_calloutPriority; + uint8_t iv_refObjIndex; + void addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const; + }; + + /// + /// @brief Structure representing a procedure callout + /// + struct ErrorInfoEntryProcCallout + { + uint8_t iv_procedure; + uint8_t iv_calloutPriority; + void addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const; + + ErrorInfoEntryProcCallout(uint8_t i_procedure, uint8_t i_calloutPriority): + iv_procedure(i_procedure), + iv_calloutPriority(i_calloutPriority) + {} + + ErrorInfoEntryProcCallout(void) = default; + }; + + /// + /// @brief Structure representing a bus callout + /// + struct ErrorInfoEntryBusCallout + { + uint8_t iv_endpoint1ObjIndex; + uint8_t iv_endpoint2ObjIndex; + uint8_t iv_calloutPriority; + void addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const; + }; + + /// + /// @brief Structure representing a target callout + /// + struct ErrorInfoEntryTargetCDG + { + uint8_t iv_targetObjIndex; + uint8_t iv_callout; + uint8_t iv_deconfigure; + uint8_t iv_gard; + uint8_t iv_calloutPriority; + void addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const; + }; + + /// + /// @brief Structure representing a child callout + /// + struct ErrorInfoEntryChildrenCDG + { + uint8_t iv_parentObjIndex; + uint8_t iv_callout; + uint8_t iv_deconfigure; + uint32_t iv_childType; + uint8_t iv_childPort; + uint8_t iv_childNumber; + uint8_t iv_gard; + uint8_t iv_calloutPriority; + void addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const; + }; + + /// + /// @brief Structure representing collected trace information + /// + struct ErrorInfoEntryCollectTrace + { + uint32_t iv_eieTraceId; + void addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const; + }; + + /// + /// @brief Union of all the error info types + /// + struct ErrorInfoEntry + { + uint8_t iv_type; // Value from ErrorInfoType + union + { + ErrorInfoEntryFfdc ffdc; + ErrorInfoEntryHwCallout hw_callout; + ErrorInfoEntryProcCallout proc_callout; + ErrorInfoEntryBusCallout bus_callout; + ErrorInfoEntryTargetCDG target_cdg; + ErrorInfoEntryChildrenCDG children_cdg; + ErrorInfoEntryCollectTrace collect_trace; + }; + + /// + /// @brief Add error information to the FFDC object + /// @param[in] i_info a shared pointer to the error info + /// @param[in] i_object the list of ffdc objects being collected + /// + void addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const + { + // "unhandled error info type"); + assert(iv_type < EI_LAST_TYPE); + + switch(iv_type) + { + case EI_TYPE_FFDC: + ffdc.addErrorInfo(i_info, i_object); + break; + case EI_TYPE_HW_CALLOUT: + hw_callout.addErrorInfo(i_info, i_object); + break; + case EI_TYPE_PROCEDURE_CALLOUT: + proc_callout.addErrorInfo(i_info, i_object); + break; + case EI_TYPE_BUS_CALLOUT: + bus_callout.addErrorInfo(i_info, i_object); + break; + case EI_TYPE_CDG: + target_cdg.addErrorInfo(i_info, i_object); + break; + case EI_TYPE_CHILDREN_CDG: + children_cdg.addErrorInfo(i_info, i_object); + break; + case EI_TYPE_COLLECT_TRACE: + collect_trace.addErrorInfo(i_info, i_object); + break; + }; + return; + } + }; +} + +#endif // FAPI2_ERRORINFO_H_ diff --git a/src/ppe/hwpf/fapi/include/error_scope.H b/src/ppe/hwpf/fapi/include/error_scope.H new file mode 100755 index 0000000..1078235 --- /dev/null +++ b/src/ppe/hwpf/fapi/include/error_scope.H @@ -0,0 +1,104 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/error_scope.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file error_scope.H + * @brief definitions which create a scope for automatic error handling + */ + +#ifndef __FAPI2_ERROR_SCOPE__ +#define __FAPI2_ERROR_SCOPE__ + +#include <stdint.h> +#include <thread> +#include <stdio.h> +#include <return_code.H> + +/// @cond +#define FAPI_VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N +#define FAPI_VA_NARGS(...) FAPI_VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1) + +#define FAPI_TRY_IMPL2(count, ...) FAPI_TRY ## count (__VA_ARGS__) +#define FAPI_TRY_IMPL(count, ...) FAPI_TRY_IMPL2(count, __VA_ARGS__) + +#define FAPI_TRY_NO_TRACE( __operation__ ) \ + if ((fapi2::current_err = (__operation__)) != fapi2::FAPI2_RC_SUCCESS) \ + { \ + goto clean_up; \ + } + +// Why debug? Because this isn't a mechanism to gather FFDC +// one should be using FAPI_ASSERT. However, it is nice to +// have a conditional trace in the event of a failure in the +// operation, so that's why this is here. +#define FAPI_TRY_TRACE( __operation__, ... ) \ + if ((fapi2::current_err = (__operation__)) != fapi2::FAPI2_RC_SUCCESS) \ + { \ + FAPI_DBG(__VA_ARGS__); \ + goto clean_up; \ + } + +#define FAPI_TRY1 FAPI_TRY_NO_TRACE +#define FAPI_TRY2 FAPI_TRY_TRACE +#define FAPI_TRY3 FAPI_TRY_TRACE +#define FAPI_TRY4 FAPI_TRY_TRACE +#define FAPI_TRY5 FAPI_TRY_TRACE +/// @endcond + +/// +/// @brief Wrapper to check an operation for an error state +/// and jump to the label cleam_up if there is an error. +/// @param[in] __operation__ an operation which returns a fapi::ReturnCode +/// @param[in] ... vararg format/agruments for trace output (optional) +/// @note This implementation does not support PIB error masks or +/// FSP operational states. +/// @warning The trace information is only going to be seen during +/// debug, it's not an error or informational trace. This is because +/// traces might not be seen in the field. If you want information +/// you will see on a field error, use FAPI_ASSERT. +/// +#ifdef DOXYGEN +#define FAPI_TRY(__operation__, ...) FAPI_TRY_IMPL +#else +#define FAPI_TRY(...) FAPI_TRY_IMPL(FAPI_VA_NARGS(__VA_ARGS__), __VA_ARGS__) +#endif + +/// +/// @brief Assert a conditional is true. +/// If it is not, the FFDC gathering function is called and the +/// trace is output as a FAPI error trace. +/// @param[in] __conditional__ the condition to assert +/// @param[in] __ffdc__ the FFDC gathering function +/// @param[in] ... varargs, as input to FAPI_ERR +/// +#define FAPI_ASSERT( __conditional__, __ffdc__, ... ) \ + if (! (__conditional__)) \ + { \ + (__ffdc__).execute(); \ + FAPI_ERR(__VA_ARGS__); \ + goto clean_up; \ + } + + +#endif diff --git a/src/ppe/hwpf/fapi/include/ffdc.H b/src/ppe/hwpf/fapi/include/ffdc.H new file mode 100755 index 0000000..6a478e7 --- /dev/null +++ b/src/ppe/hwpf/fapi/include/ffdc.H @@ -0,0 +1,193 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/ffdc.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/** + * @file ffdc.H + * @brief Defines the FirstFailureData class + */ + +#ifndef FAPI2_FFDC_H_ +#define FAPI2_FFDC_H_ + +#include <memory> +#include <hwp_return_codes.H> +#include <plat_trace.H> +#include <error_info.H> +#include <target.H> +#include <assert.h> + +using fapi2::TARGET_TYPE_ALL; + +namespace fapi2 +{ + /// + /// @brief Check the type of a variable + /// + /// This function can be called to check that a variable type is as expected + /// @note This mechanism will allow for cast ctor's which other static type + /// checking might not. + /// + template<typename T> + inline + void checkType(const T &) {} + + class ReturnCode; + + /// + /// @class FirstFailureData + /// + /// This class provides storage and methods for creating and manipulating + /// FFDC. + /// It is not needed on all platforms - platforms which need this class have + /// specified this by forcing their fapi2::ReturnCode to be a subclass of + /// this class. + /// + template< class R = fapi2::ReturnCode > + class FirstFailureData + { + public: + + /// + /// @brief Default constructor. + /// @note We don't create our error info be default. It will be created + /// when its needed in the setHwpError() method. Note that dereferencing + /// the error info without will create a problem. + /// + FirstFailureData(void): + iv_info( nullptr ) + {} + + /// + /// @brief Copy Constructor + /// + /// @param[in] i_right Reference to FirstFailureData to copy + /// @note Generates default copy constructor - no deep pointer + /// copies necessary. + /// + FirstFailureData(const FirstFailureData & i_right) = default; + + /// + /// @brief Destructor + /// + ~FirstFailureData(void) = default; + + /// + /// @brief Assignment Operator. + /// + /// @param[in] i_right Reference to FirstFailureData to assign from. + /// @return Reference to 'this' FirstFailureData + /// + FirstFailureData & operator=(const FirstFailureData & i_right) = default; + + /// + /// @brief Sets a HWP error. Sets the rcValue to the supplied value (from + /// the HwpFirstFailureData enumeration) and deletes any + /// associated data. + /// + /// HWP code must call the FAPI_SET_HWP_ERROR macro rather than this + /// function + /// directly to generate an error so that any error information is + /// automatically added to the FirstFailureData + /// + /// @param[in] i_rcValue Error value to set + /// + inline void _setHwpError(const fapi2::HwpReturnCode i_rcValue) + { + FAPI_ERR("_setHwpError: Creating HWP error 0x%x", i_rcValue); + static_cast<R*>(this)->operator=(i_rcValue); + + // Forget about any associated data (this is a new error) + iv_info.reset(new ErrorInfo()); + } + + /// + /// @brief Get a pointer to any PlatData. FirstFailureData is still + /// responsible for deletion of the data. The caller must not + /// delete + /// + /// This is called by PLAT. The expected use-case is to get a pointer to + /// a platform error log. The data pointer should be used immediately in + /// the same thread. + /// + /// @return void *. Pointer to any PlatData. If NULL then no data + /// + void* getData(void) const; + + /// + /// @brief Get a pointer to any PlatData and release ownership from + /// FirstFailureData. The caller is responsible for deletion. + /// + /// This is called by PLAT. The expected use-case is to retrieve a + /// platform error log. + /// + /// @return void*. Pointer to any PlatData. If NULL then no data + /// + void* releaseData(void); + + /// + /// @brief Add ErrorInfo + /// + /// This is called by the FAPI_SET_HWP_ERROR and macro to add ErrorInfo + /// to the FirstFailureData when a HWP generates an error. The function + /// is designed to add all the ErrorInfo at once rather than the + /// FAPI_SET_HWP_ERROR macro making multiple function calls to add each + /// piece of ErrorInfo individually in order to minimize code size + /// + /// @param[in] i_pObjects Pointer to array of const pointers to const + /// objects that are referred to by ErrorInfoEntry objects + /// @param[in] i_pEntries Pointer to array of ErrorInfoEntry objects + /// defining the ErrorInfo that needs to be added + /// @param[in] i_count Number of ErrorInfoEntry entries + /// + void addErrorInfo(const void* const * i_pObjects, + const ErrorInfoEntry* i_pEntries, + const uint8_t i_count); + + /// + /// @brief Get a pointer to any ErrorInfo + /// + /// This is called by PLAT to find information about an error + /// + /// @return ErrorInfo *. Pointer to any ErrorInfo. If NULL then no info + /// + inline const fapi2::ErrorInfo* getErrorInfo(void) const + { return iv_info.get(); } + + /// + /// @brief Forgets about any associated data (PlatData and ErrorInfo) + /// + /// If this is the only FirstFailureData pointing to the data then the + /// data is deleted + /// + inline void forgetData(void) + { iv_info = nullptr; } + + private: + + // Pointer to the data + std::shared_ptr<ErrorInfo> iv_info; + }; + +}; +#endif // FAPI2_FFDC_H_ diff --git a/src/ppe/hwpf/fapi/include/hw_access.H b/src/ppe/hwpf/fapi/include/hw_access.H new file mode 100755 index 0000000..8b915c6 --- /dev/null +++ b/src/ppe/hwpf/fapi/include/hw_access.H @@ -0,0 +1,720 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/hw_access.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file hw_access.H + * + * @brief Defines the hardware access functions that platform code must + * implement. + */ + +#ifndef FAPI2_HWACCESS_H_ +#define FAPI2_HWACCESS_H_ + +#ifdef FAPI_SUPPORT_SPY_AS_ENUM +#include <fapiSpyIds.H> +#endif + +#include <stdint.h> +#include <thread> +#include <buffer.H> +#include <variable_buffer.H> +#include <return_code.H> +#include <target.H> + +#ifdef FAPI_SUPPORT_MULTI_SCOM +#include <fapiMultiScom.H> +#endif + +/// @cond +typedef uint64_t spyId_t; +typedef uint64_t scanRingId_t; +/// @endcond + +namespace fapi2 +{ + + /// + /// @enum fapi2::ChipOpModifyMode + /// @brief Enumeration of modify modes used in HW access modify operations + /// + enum ChipOpModifyMode + { + CHIP_OP_MODIFY_MODE_OR = 1, ///< Modify or mode + CHIP_OP_MODIFY_MODE_AND = 2, ///< Modify and mode + CHIP_OP_MODIFY_MODE_XOR = 3, ///< Modify xor mode + }; + + /// + /// @enum fapi2::RingMode + /// @brief Enumeration of Ring access operation modes + /// This is a bitmap to allow the user to specify multiple modes. + /// + enum RingMode + { + RING_MODE_SET_PULSE = 0x00000001, ///< Set pulse + RING_MODE_NO_HEADER_CHECK = 0x00000002, ///< Dont' check header + // FUTURE_MODE = 0x00000004, + // FUTURE_MODE = 0x00000008, + }; + + //-------------------------------------------------------------------------- + // PIB Error Functions + //-------------------------------------------------------------------------- + + /// @brief Sets the PIB error mask - platform dependant + /// @param[in] i_mask The new error mask + inline void setPIBErrorMask(uint8_t i_mask) + { + // Platform specific funtion needs to be defined here. + // For Cronus/FSP/Hostboot, this is a no-op. + return; + } + + /// @brief Gets the PIB error mask - platform dependant + /// @return uint8_t The current PIB error mask + inline uint8_t getPIBErrorMask(void) + { + // Platform specific funtion needs to be defined here. + // For Cronus/FSP/Hostboot, this always returns 0 + return 0; + } + + //-------------------------------------------------------------------------- + // Operational Mode Error Functions + //-------------------------------------------------------------------------- + + /// @enum OpModes operational Mode Error Functions + enum OpModes + { + // These are bit-masks in case they need to be or'd together + NORMAL = 0x00, + IGNORE_HW_ERROR = 0x01, + DO_NOT_DO_WAKEUP = 0x02, + }; + + /// @brief Sets the operational mode + /// @param[in] i_mode The new mode + inline void setOpMode(const OpModes i_mode) + { + // No-op for now. Should set thread-local operational mode + return; + } + + /// @brief Gets the operational mode + /// @return the operational mode + inline OpModes getOpMode(void) + { + // No-op for now. Should read thread-local operational mode + return NORMAL; + } + + //-------------------------------------------------------------------------- + // HW Communication Functions + //-------------------------------------------------------------------------- + + /// @brief Reads a SCOM register from a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address SCOM register address to read from. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode getScom(const Target<K>& i_target, const uint64_t i_address, + buffer<uint64_t>& o_data) + { + o_data = 0x0000FEEDFACE0000; + std::cout << std::hex << " getScom " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "address: " << i_address << "; " + << "output data: " << uint64_t(o_data) + << std::dec << std::endl; + return FAPI2_RC_SUCCESS; + } + + /// @brief Writes a SCOM register on a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address SCOM register address to write to. + /// @param[in] i_data Buffer that holds data to write into address. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode putScom(const Target<K>& i_target, const uint64_t i_address, + buffer<uint64_t>& i_data) + { + std::cout << std::hex << " putScom " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "address: " << i_address << "; " + << "input data: " << uint64_t(i_data) + << std::dec << std::endl; + return FAPI2_RC_SUCCESS; + } + + /// @brief Read-modify-write a SCOM register on a chip + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address SCOM register address to write to. + /// @param[in] i_data Buffer that holds data to be modified. + /// @param[in] i_modifyMode The modify mode (or/and/xor). + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode modifyScom(const Target<K>& i_target, + const uint64_t i_address, + const buffer<uint64_t>& i_data, + const ChipOpModifyMode i_modifyMode) + { + fapi2::buffer<uint64_t> l_modifyDataBuffer = i_data; + std::cout << std::hex << " modifyScom " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "address: " << i_address << "; " + << "input modifying data: " << uint64_t(l_modifyDataBuffer) << "; " + << "input ChipOpModifyMode: " << i_modifyMode + << std::dec << std::endl; + return FAPI2_RC_SUCCESS; + } + + /// @brief Writes a SCOM register under mask on a chip + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address SCOM register address to write to. + /// @param[in] i_data Buffer that holds data to write into address. + /// @param[in] i_mask Buffer that holds the mask value. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode putScomUnderMask(const Target<K>& i_target, + const uint64_t i_address, + buffer<uint64_t>& i_data, + buffer<uint64_t>& i_mask) + { + std::cout << std::hex << " putScomUnderMask " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "address: " << i_address << "; " + << "input data: " << uint64_t(i_data) << "; " + << "input mask: " << uint64_t(i_mask) + << std::dec << std::endl; + return FAPI2_RC_SUCCESS; + } + + /// @brief Reads a CFAM register from a chip. + /// CFAM register is 32-bit wide. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address CFAM register address to read from. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode getCfamRegister(const Target<K>& i_target, + const uint32_t i_address, + buffer<uint32_t>& o_data) + { + o_data = 0xFEED0CFA; + std::cout << std::hex << " getCfamRegister " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "address: " << i_address << "; " + << "output data: " << uint32_t(o_data) + << std::dec << std::endl; + return FAPI2_RC_SUCCESS; + } + + /// @brief Writes a CFAM register on a chip. + /// CFAM register is 32-bit wide. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address CFAM register address to write to. + /// @param[in] i_data Buffer that holds data to write into address. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode putCfamRegister(const Target<K>& i_target, + const uint32_t i_address, + buffer<uint32_t>& i_data) + { + std::cout << std::hex << " putCfamRegister " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "address: " << i_address << "; " + << "input data: " << uint32_t(i_data) + << std::dec << std::endl; + return FAPI2_RC_SUCCESS; + } + + /// @brief Read-modify-write a CFAM register on a chip. + /// CFAM register is 32-bit wide. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address CFAM register address to modify. + /// @param[in] i_data Buffer that holds data to be modified. + /// @param[in] i_modifyMode The modify mode (or/and/xor). + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode modifyCfamRegister(const Target<K>& i_target, + const uint32_t i_address, + const buffer<uint32_t>& i_data, + const ChipOpModifyMode i_modifyMode) + { + fapi2::buffer<uint32_t> l_modifyDataBuffer = i_data; + std::cout << std::hex << " modifyCfamRegister " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "address: " << i_address << "; " + << "input modifying data: " << uint32_t(l_modifyDataBuffer) << "; " + << "input ChipOpModifyMode: " << i_modifyMode + << std::dec << std::endl; + return FAPI2_RC_SUCCESS; + } + + /// @brief Reads a ring from a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_address Ring address to read from. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @param[in] i_ringMode Ring operation mode. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode getRing(const Target<K>& i_target, + const scanRingId_t i_address, + variable_buffer& o_data, + const RingMode i_ringMode = 0) + { + o_data.setBit(0); + o_data.setBit(3); + std::cout << std::hex << " getRing " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "ring address: " << i_address << "; " + << "ring mode: " << i_ringMode << "; " + << "output data:"; + o_data.print(); + + return FAPI2_RC_SUCCESS; + } + + /// @brief Writes a ring to a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_address Ring address to write to. + /// @param[in] i_data Buffer that contains RS4 compressed ring data + /// to write into address + /// @param[in] i_ringMode Ring operation mode. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode putRing(const Target<K>& i_target, + const scanRingId_t i_address, + variable_buffer& i_data, + const RingMode i_ringMode = 0) + { + std::cout << std::hex << " putRing " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "address: " << i_address << "; " + << "ring mode: " << i_ringMode << "; " + << "input data:"; + i_data.print(); + + return FAPI2_RC_SUCCESS; + } + + + /// @brief Writes a ring to a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_address Ring address to write to. + /// @param[in] i_data Pointer to location that contains RS4 compressed + // ring data to write into address + /// @param[in] i_ringMode Ring operation mode. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode putRing(const Target<K>& i_target, + const scanRingId_t i_address, + const void* i_data, + const RingMode i_ringMode = 0) + { + uint64_t* dataPtr = reinterpret_cast<uint64_t*>(const_cast<void*>(i_data)); + std::cout << std::hex << " putRing (void*) " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "address: " << i_address << "; " + << "ring mode: " << i_ringMode << "; " + << "input data: " << (uint64_t)(*dataPtr) + << (uint64_t)*(dataPtr+1) + << (uint64_t)*(dataPtr+2) + << (uint64_t)*(dataPtr+3); + std::cout << std::dec << std::endl; + + return FAPI2_RC_SUCCESS; + } + + /// @brief Read-modify-write a ring on a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_address Ring address to modify. + /// @param[in] i_data Buffer that contains RS4 compressed ring data + /// to be modified. + /// @param[in] i_modifyMode The modify mode (or/and/xor) + /// @param[in] i_ringMode Ring operation mode. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode modifyRing(const Target<K>& i_target, + const scanRingId_t i_address, + variable_buffer& i_data, + const ChipOpModifyMode i_modifyMode, + const RingMode i_ringMode = 0) + { + std::cout << std::hex << " modifyRing " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "address: " << i_address << "; " + << "input ChipOpModifyMode: " << i_modifyMode << "; " + << "ring mode: " << i_ringMode << "; " + << "input data: "; + i_data.print(); + + return FAPI2_RC_SUCCESS; + } + + /// @note + /// These spy access interfaces are only used in FSP and cronus + /// HB does not allow spy access + +#if defined(FAPI_SUPPORT_SPY_AS_ENUM) || defined(FAPI_SUPPORT_SPY_AS_STRING) || defined(DOXYGEN) + /// @brief Reads a spy from a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_spyId Id of the spy whose data to be read. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependant on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// 1. if the spy name contains a # procedure writers should replace + /// it with an __P__ for example - + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// becomes + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// 2. if the spy name has a number following a "." it must have an + /// underscore prepended to the number. + /// + /// EH.TPCHIP.2KX100_ARY_CLK_EDGES_DLY + /// becomes + /// EH.TPCHIP._2KX100_ARY_CLK_EDGES_DLY + /// + /// Example SPY name: + /// The hardware procedure should call the function like: + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// fapi::ReturnCode rc = fapiGetSpy( targ, + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS, data ); + /// + /// @note The ID is not in quotes the fapi code will handle adding + /// the quotes for the cronus environment + /// +#endif + +// Set to 1 for fapi2 API test +#define FAPI_SUPPORT_SPY_AS_ENUM 1 + +#ifdef FAPI_SUPPORT_SPY_AS_ENUM + +#ifndef DOXYGEN +#define fapiGetSpy(TARGET, ID, DATA) \ + _fapiGetSpy(TARGET, FAPI_SPY_NAMES::ID.value, DATA ) +#endif + template< TargetType K > + inline ReturnCode _fapiGetSpy(const Target<K>& i_target, + const spyId_t i_spyId, + variable_buffer& o_data) + { + o_data.setBit(1); + o_data.setBit(4); + std::cout << std::hex << " _fapiGetSpy " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "Spy ID: " << i_spyId << "; " + << "output data:"; + o_data.print(); + + return FAPI2_RC_SUCCESS; + } + +#endif + +#ifdef FAPI_SUPPORT_SPY_AS_STRING + +#ifndef DOXYGEN +#define fapiGetSpy(TARGET, ID, DATA) _fapiGetSpy(TARGET, #ID, DATA) +#endif + template< TargetType K > + inline ReturnCode _fapiGetSpy(const Target<K>& i_target, + const char * const i_spyId, + variable_buffer& o_data); +#endif + +#if defined(FAPI_SUPPORT_SPY_AS_ENUM) || defined(FAPI_SUPPORT_SPY_AS_STRING) || defined(DOXYGEN) + /// @brief Writes a spy on a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_spyId Id of the spy to write data to. + /// @param[out] i_data Buffer that holds data to write into spy. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependent on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// 1. if the spy name contains a # procedure writers should replace + /// is with an __P__ for example - + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// becomes + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// 2. if the spy name has a number following a "." it must have an + /// underscore prepended to the number. + /// + /// EH.TPCHIP.2KX100_ARY_CLK_EDGES_DLY + /// becomes + /// EH.TPCHIP._2KX100_ARY_CLK_EDGES_DLY + /// + /// Example SPY name: + /// The hardware procedure should call the function like: + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// fapi::ReturnCode rc = fapiPutSpy( targ, + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS, data ); + /// + /// @note The ID is not in quotes the fapi code will handle adding + /// the quotes for the cronus environment + /// +#endif + +#ifdef FAPI_SUPPORT_SPY_AS_ENUM +#ifndef DOXYGEN +#define fapiPutSpy(TARGET, ID, DATA) \ + _fapiPutSpy(TARGET, FAPI_SPY_NAMES::ID.value, DATA) +#endif + template< TargetType K > + inline ReturnCode _fapiPutSpy(const Target<K>& i_target, + const spyId_t i_spyId, + variable_buffer& i_data) + { + std::cout << std::hex << " _fapiPutSpy " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "Spy Id: " << i_spyId << "; " + << "input data:"; + i_data.print(); + + return FAPI2_RC_SUCCESS; + } +#endif + +#ifdef FAPI_SUPPORT_SPY_AS_STRING +#ifndef DOXYGEN +#define fapiPutSpy(TARGET, ID, DATA) _fapiPutSpy(TARGET, #ID, DATA) +#endif + template< TargetType K > + inline ReturnCode _fapiPutSpy(const Target<K>& i_target, + const char* const i_spyId, + variable_buffer& i_data); +#endif + +#if defined(FAPI_SUPPORT_SPY_AS_ENUM) || defined(FAPI_SUPPORT_SPY_AS_STRING) + + /// @brief Writes spy data into a buffer holding ring data image + /// This API is used by L2/L3 repair to put column repair data + /// into a ring buffer image. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_spyId Id of the spy. + /// @param[in] i_data Buffer that holds spy data to write into ring + /// image. + /// @param[out] o_data Buffer that holds updated ring image. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependent on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// See fapiPutSpy for details on spy id specifics. + /// +#endif + +#ifdef FAPI_SUPPORT_SPY_AS_ENUM +#ifndef DOCUMENTATION +#define fapiPutSpyImage(TARGET, ID, DATA1, DATA2) \ + _fapiPutSpyImage(TARGET, \ + FAPI_SPY_NAMES::ID.value, \ + DATA1, DATA2) +#endif + template< TargetType K > + inline ReturnCode _fapiPutSpyImage(const Target<K>& i_target, + const spyId_t i_spyId, + variable_buffer& i_data, + variable_buffer& o_imageData) + { + std::cout << std::hex << " _fapiPutSpyImage " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "Spy Id: " << i_spyId << "; " + << "input data: "; + i_data.print(); + + // Set fake output data + o_imageData.invert(); + + return FAPI2_RC_SUCCESS; + } +#endif + +#ifdef FAPI_SUPPORT_SPY_AS_STRING +// fapiPutSpyImage function Cronus version +#ifndef DOCUMENTATION +#define fapiPutSpyImage(TARGET, ID, DATA1, DATA2) \ + _fapiPutSpyImage(TARGET, #ID, \ + DATA1,DATA2) +#endif + + template< TargetType K > + inline ReturnCode _fapiPutSpyImage(const Target<K>& i_target, + const char* const i_spyId, + variable_buffer& i_data, + variable_buffer& o_imageData); +#endif + +#if defined(FAPI_SUPPORT_SPY_AS_ENUM) || defined(FAPI_SUPPORT_SPY_AS_STRING) || defined(DOXYGEN) + /// @brief Reads spy data from a ring image buffer + /// @param[in] i_target Target to operate on + /// @param[in] i_spyId The spy's id + /// @param[out] o_data Buffer that holds data read from ring image. + /// @param[in] i_imageData Buffer that holds ring image to read data + /// from. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependent on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// See fapiPutSpy for details on spy id specifics. + /// +#endif + +#ifdef FAPI_SUPPORT_SPY_AS_ENUM +#ifndef DOXYGEN +#define fapiGetSpyImage(TARGET, ID, DATA1, DATA2) \ + _fapiGetSpyImage(TARGET, \ + FAPI_SPY_NAMES::ID.value, \ + DATA1, DATA2) +#endif + template< TargetType K > + inline ReturnCode _fapiGetSpyImage(const Target<K>& i_target, + const spyId_t i_spyId, + variable_buffer& o_data, + const variable_buffer& i_imageData); +#endif + +#ifdef FAPI_SUPPORT_SPY_AS_STRING +// fapiGetSpyImage function Cronus version +#ifndef DOXYGEN +#define fapiGetSpyImage(TARGET, ID, DATA1, DATA2) \ + _fapiGetSpyImage(TARGET, \ + #ID, DATA1,DATA2) +#endif + + inline fapi::ReturnCode _fapiGetSpyImage( + const fapi::Target& i_target, + const char* const i_spyId, + fapi::buffer<fapi::bits_container> & o_data, + const fapi::buffer<fapi::bits_container> & i_imageData); +#endif + +#if defined(FAPI_SUPPORT_MULTI_SCOM) || defined(DOXYGEN) + + /// @brief Performs a multiple SCOM operation + /// This interface performs multiple SCOM operations on a chip in the + /// order specified by the input MultiScom object. + /// See fapiMultiScom.H for details of how to populate the MultiScom + /// object with SCOM operations. + /// + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in,out] io_multiScomObj Reference to a MultiScom object, + /// pre-populated with SingleScomInfo entries + /// to perform multiple SCOMs on input target + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note This is a synchronous interface and would return after all the + /// SCOM operations are completed or on the first failed operation + /// + /// @note SCOMs will be performed in the order they were added to the + /// input MultiScom object + /// + /// @note In case of errors, the platform code is responsible to collect + /// and add all the required error info and FFDC into the error data + /// for debugging + /// + /// @note If the SCOM operations added are specific to a processor chip, + /// then the FSI Shift Engine configured in scatter-gather DMA mode + /// extension would be used to execute the SCOM operations in a + /// performance optimize mode. In this mode, the special + /// SCOM_BULK_READ_MODE and SCOM_BULK_WRITE_MODE operations are + /// supported that allow a large bulk of SCOM access (in multiple of + /// 64 bits) for targets that support auto-increment. The + /// SCOM_WRITE_UNDER_MASK operation is not supported in this mode + /// + /// @note If the SCOM operations added are specific to a memory buffer + /// chip, then the regular SCOM engine is used to execute the SCOM + /// operations. SCOM_WRITE_UNDER_MASK operation is supported in + /// this mode, but the special SCOM_BULK_READ_MODE and + /// SCOM_BULK_WRITE_MODE operations are not supported due to + /// hardware limitations. + /// + fapi::ReturnCode fapiMultiScom (const Target<K>& i_target, + MultiScom& io_multiScomObj); +#endif // FAPI_SUPPORT_MULTI_SCOM + +}; + +#endif // FAPI2HWACCESS_H_ diff --git a/src/ppe/hwpf/fapi/include/plat_trace.H b/src/ppe/hwpf/fapi/include/plat_trace.H new file mode 100755 index 0000000..38da71d --- /dev/null +++ b/src/ppe/hwpf/fapi/include/plat_trace.H @@ -0,0 +1,64 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/plat_trace.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,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 */ +/** + * @file plat_trace.H + * @brief Defines the FAPI2 trace macros. + * + * Note that platform code must provide the implementation. + * + * FAPI has provided a default implementation. Platform code must + * provide an alternate implementation if needed. + */ + +#ifndef FAPI2_PLATTRACE_H_ +#define FAPI2_PLATTRACE_H_ + +#include <stdio.h> + +#define MAX_ECMD_STRING_LEN 64 + +// Information traces (go into fast trace buffer that can wrap often) +#define FAPI_TRACE(_id_, _fmt_, _args_...) \ + printf("%s: %s:%d ", _id_, __func__, __LINE__); \ + printf(_fmt_, ##_args_); \ + printf("\n") + +#define FAPI_INF(_fmt_, _args_...) FAPI_TRACE("inf", _fmt_, ##_args_) + +// Important traces (go into slow trace buffer that should not wrap often) +#define FAPI_IMP(_fmt_, _args_...) FAPI_TRACE("imp", _fmt_, ##_args_) + +// Error traces (go into slow trace buffer that should not wrap often) +#define FAPI_ERR(_fmt_, _args_...) FAPI_TRACE("err", _fmt_, ##_args_) + +// Debug traces (go into fast trace buffer that can wrap often) +#define FAPI_DBG(_fmt_, _args_...) FAPI_TRACE("dbg", _fmt_, ##_args_) + +// Scan traces +#define FAPI_SCAN(_fmt_, _args_...) FAPI_TRACE("scan", _fmt_, ##_args_) + +#define FAPI_MFG(_fmt_, _args_...) FAPI_TRACE("mfg", _fmt_, ##_args_) + +#endif // FAPI2_PLATTRACE_H_ diff --git a/src/ppe/hwpf/fapi/include/return_code.H b/src/ppe/hwpf/fapi/include/return_code.H new file mode 100755 index 0000000..f1b4451 --- /dev/null +++ b/src/ppe/hwpf/fapi/include/return_code.H @@ -0,0 +1,180 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/return_code.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file return_code.H + * @brief definitions for fapi2 return codes + */ + +#ifndef __FAPI2_RETURN_CODE__ +#define __FAPI2_RETURN_CODE__ + +#include <stdint.h> + +// Remove this for platforms which don't support FFDC +#include <ffdc.H> + +/// +/// @brief Set HWP Error macro +/// +/// This macro should be used by a HWP to create an error. The ReturnCode's +/// internal return code is set and any error information in the Error XML file +/// is added to the ReturnCode +/// +#define FAPI_SET_HWP_ERROR(RC, ERROR) \ + RC._setHwpError(fapi2::ERROR); \ + ERROR##_CALL_FUNCS_TO_COLLECT_FFDC(RC); \ + ERROR##_CALL_FUNCS_TO_COLLECT_REG_FFDC(RC); \ + ERROR##_ADD_ERROR_INFO(RC) + +/// +/// @brief Add info to HWP Error macro +/// +/// This macro should be used by an FFDC HWP to add error information from an +/// Error XML file to an existing error. +/// +#define FAPI_ADD_INFO_TO_HWP_ERROR(RC, ERROR) \ + ERROR##_CALL_FUNCS_TO_COLLECT_FFDC(RC); \ + ERROR##_CALL_FUNCS_TO_COLLECT_REG_FFDC(RC); \ + ERROR##_ADD_ERROR_INFO(RC) + +namespace fapi2 +{ + /// + /// @brief Enumeration of return codes + /// + enum ReturnCodes + { + ///< Success + FAPI2_RC_SUCCESS = 0, + + // Flag bits indicating which code generated the error. + FAPI2_RC_FAPI2_MASK = 0x04000000, ///< FAPI2 mask + FAPI2_RC_PLAT_MASK = 0x02000000, ///< Platform mask + FAPI2_RC_HWP_MASK = 0x00000000, ///< HWP mask + + // + // FAPI generated return codes + // + + FAPI2_RC_INVALID_ATTR_GET = FAPI2_RC_FAPI2_MASK | 0x01, + ///< Initfile requested an attribute with an invalid attribute ID + + FAPI2_RC_INVALID_CHIP_EC_FEATURE_GET = FAPI2_RC_FAPI2_MASK | 0x02, + ///< HWP requested a chip EC feature with an invalid attribute ID + + FAPI2_RC_INVALID_MULTISCOM_LENGTH = FAPI2_RC_FAPI2_MASK | 0x03, + ///< Invalid multiscom parameters + + FAPI2_RC_INVALID_PARAMETER = FAPI2_RC_FAPI2_MASK | 0x04, + ///< Invalid parameters to a FAPI2 function + + FAPI2_RC_OVERFLOW = FAPI2_RC_FAPI2_MASK | 0x05, + ///< Overflow condition, typically a buffer operation + + // + // PLAT generated return codes. Additional details may be contained in + // ReturnCode platData (this can only be looked at by PLAT code) + // + + FAPI2_RC_PLAT_ERR_SEE_DATA = FAPI2_RC_PLAT_MASK | 0x01, + ///< Generic platform error + + FAPI2_RC_PLAT_ERR_ADU_LOCKED = FAPI2_RC_PLAT_MASK | 0x02, + ///< Operation to AlterDisplay unit failed because it is locked + + FAPI2_RC_PLAT_NOT_SUPPORTED_AT_RUNTIME = FAPI2_RC_PLAT_MASK | 0x03, + ///< Operation not supported by HB runtime + }; + + /// + /// @brief Class representing a FAPI2 ReturnCode + /// + /// @note Remove the inheritance relationship with FirstFailureData if + /// the platform doesn't support FFDC. + class ReturnCode : public FirstFailureData<ReturnCode> + { + public: + + /// + /// @brief Constructor. + /// @param[in] i_rc the rc to set + /// + ReturnCode(const uint64_t i_rc = FAPI2_RC_SUCCESS): + iv_rc(i_rc) + {}; + + /// + /// @brief integral type conversion function. Returns the error code + /// @return The error code + /// + inline operator uint64_t() const { return iv_rc; } + + /// + /// @brief Returns true iff iv_rc == SUCCESS + /// @return true or false + /// + inline operator bool() const { return iv_rc == FAPI2_RC_SUCCESS; } + + /// + /// @brief Assignement operator + /// + inline ReturnCode& operator=(const uint64_t& rhs) + { + iv_rc = rhs; + return *this; + } + + inline ReturnCode& operator=(const ReturnCodes& rhs) + { + iv_rc = rhs; + return *this; + } + + inline bool operator==(const uint64_t& rhs) const + { return rhs == iv_rc; } + + inline bool operator==(const ReturnCodes& rhs) const + { return rhs == iv_rc; } + + inline bool operator!=(const uint64_t& rhs) const + { return rhs != iv_rc; } + + inline bool operator!=(const ReturnCodes& rhs) const + { return rhs != iv_rc; } + + private: + uint64_t iv_rc; + }; + + /// This implementation assumes no exception handling and leverages thread-local + /// storage. For platforms without thread support, a global variable will + /// suffice for the error state. + extern thread_local ReturnCode current_err; /// the current error state + extern thread_local uint64_t pib_error_mask; /// the pib mask + extern thread_local uint64_t operational_state; /// the operational mode + +}; + +#endif diff --git a/src/ppe/hwpf/fapi/include/target.H b/src/ppe/hwpf/fapi/include/target.H new file mode 100755 index 0000000..3eacb17 --- /dev/null +++ b/src/ppe/hwpf/fapi/include/target.H @@ -0,0 +1,337 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/target.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file target.H + * @brief definitions for fapi2 targets + */ + +#ifndef __FAPI2_TARGET__ +#define __FAPI2_TARGET__ + +#include <stdint.h> +#include <vector> +#include <target_types.H> +#include <stdio.h> + +namespace fapi2 +{ + /// + /// @brief Enumeration of target state values (bitmask values) + /// + enum TargetState + { + TARGET_STATE_PRESENT = 0x00000001, + TARGET_STATE_FUNCTIONAL = 0x00000002, + }; + + /// + /// @brief Class representing a FAPI2 Target + /// @tparam K the type (Kind) of target + /// @tparam V the type of the target's Value + /// @remark TargetLite targets are uint64_t, Targets + /// are uintptr_t (void*). + /// + /// Assuming there are representations of a processor, + /// a membuf and a system here are some examples: + /// @code + /// #define PROCESSOR_CHIP_A 0xFFFF0000 + /// #define MEMBUF_CHIP_B 0x0000FFFF + /// #define SYSTEM_C 0x0000AAAA + /// @endcode + /// + /// * To define a target: + /// @code + /// fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> A(PROCESSOR_CHIP_A); + /// fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> C(SYSTEM_C); + /// fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> B(MEMBUF_CHIP_B); + /// @endcode + /// + /// * Functions which take composite target types + /// @code + /// void takesProcOrMembuf( + /// const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP | + /// fapi2::TARGET_TYPE_MEMBUF_CHIP>& V ); + /// + /// void takesAny(const fapi2::Target<fapi2::TARGET_TYPE_ALL>& V ); + /// + /// @endcode + /// + /// * Traversing the target "tree" + /// @code + /// fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> A(PROCESSOR_CHIP_A); + /// + /// // Get A's parent + /// A.getParent<fapi2::TARGET_TYPE_SYSTEM>(); + /// + /// // Get the 0x53'd core + /// fapi2::getTarget<fapi2::TARGET_TYPE_CORE>(0x53); + /// + /// // Get all *my* present/functional children which are cores + /// A.getChildren<fapi2::TARGET_TYPE_CORE>(); + /// + /// // Get all of the the cores relative to my base target + /// fapi2::getChildren<fapi2::TARGET_TYPE_CORE>(); + /// @endcode + /// + /// * Invalid casts + /// @code + /// // Can't cast to a specialized target + /// fapi2::Target<fapi2::TARGET_TYPE_NONE> D(MEMBUF_CHIP_B); + /// takesProcOrMembuf( D ); + /// + /// // Not one of the shared types + /// fapi2::Target<fapi2::TARGET_TYPE_ABUS_ENDPOINT> E; + /// takesProcOrMembuf( E ); + /// @endcode + template<TargetType K, typename V = uint64_t> + class Target + { + public: + + /// + /// @brief Create a Target, with a value + /// @param[in] Value the value (i.e., specific element this + /// target represents, or pointer) + /// @note Platforms can mangle the value and K to get a + /// single uint64_t in value which represents all the information + /// they might need. value( K | V ), for example + /// + Target(V Value = 0): + iv_handle(Value) + {} + + /// + /// @brief Assignment Operator. + /// @param[in] i_right Reference to Target to assign from. + /// @return Reference to 'this' Target + /// + Target& operator=(const Target& i_right) + { iv_handle = i_right.iv_handle; return *this; } + + /// + /// @brief Equality Comparison Operator + /// @param[in] i_right Reference to Target to compare. + /// @return bool. True if equal. + /// @note Platforms need to define this so that the physical + /// targets are determined to be equivilent rather than just the handles + /// + bool operator==(const Target& i_right) const + { return i_right.iv_handle == iv_handle; } + + /// + /// @brief Inquality Comparison Operator + /// @param[in] i_right Reference to Target to compare. + /// @return bool. True if not equal. + /// @note Platforms need to define this so that the physical + /// targets are determined to be equivilent rather than just the handles + /// + bool operator!=(const Target& i_right) const + { return i_right.iv_handle != iv_handle; } + + /// + /// @brief Get the handle. + /// @return V The target's handle, or value + /// + V get(void) const + { return iv_handle; } + + /// + /// @brief Get the handle as a V + /// @return V The target's handle, or value + /// + inline operator V() const { return iv_handle; } + + /// + /// @brief Get a target's value + /// @return V The target's handle, or value + /// + inline V& operator()(void) { return iv_handle; } + + /// + /// @brief Get the target type + /// @return The type of target represented by this target + /// + inline TargetType getType(void) const { return iv_type; } + + /// + /// @brief Get this target's immediate parent + /// @tparam T The type of the parent + /// @return Target<T> a target representing the parent + /// + template< TargetType T > + inline Target<T> getParent(void) const + { + // For testing + return Target<T>(iv_handle); + } + + /// + /// @brief Get this target's children + /// @tparam T The type of the parent + /// @param[in] i_state The desired TargetState of the children + /// @return std::vector<Target<T> > a vector of present/functional + /// children + /// + template< TargetType T> + inline std::vector<Target<T> > + getChildren(const TargetState i_state = TARGET_STATE_FUNCTIONAL) const + { + // For testing + return {Target<T>()}; + } + + /// + /// @brief Get the target at the other end of a bus - dimm included + /// @tparam T The type of the parent + /// @param[in] i_state The desired TargetState of the children + /// @return Target<T> a target representing the thing on the other end + /// @note Can be easily changed to a vector if needed + /// + template<TargetType T> + inline Target<T> + getOtherEnd(const TargetState i_state = TARGET_STATE_FUNCTIONAL) const + { + // Implementation note: cast to a composite of + // bus types and the compiler will check if this is + // a good function at compile time + return Target<T>(); + } + + /// + /// @brief Copy from a Target<O> to a Target<K> + /// @tparam O the target type of the other + /// + template<TargetType O> + inline Target( const Target<O>& Other ): + Target<K, V>(Other.get()) + { + static_assert( (K & O) != 0, + "unable to cast Target, no shared types"); + + static_assert( bitCount<K>::count >= bitCount<O>::count, + "unable to cast to specialized Target"); + } + + private: + // Don't use enums here as it makes it hard to assign + // in the platform target cast constructor. + static const TargetType iv_type = K; + V iv_handle; + + }; + + /// + /// @brief Return the string interpretation of this target + /// @tparam T The type of the target + /// @tparam B The type of the buffer + /// @param[in] i_target Target<T> + /// @param[in] i_buffer buffer + /// @return void + /// @post The contents of the buffer is replaced with the string + /// representation of the target + /// + template< TargetType T > + inline void toString(const Target<T>& i_target, char* i_buffer, size_t i_bsize) + { + snprintf(i_buffer, i_bsize, "Target 0x%lx/0x%x", i_target.get(), T); + } + + /// + /// @brief Return the string interpretation of this target + /// @tparam T The type of the target + /// @tparam B The type of the buffer + /// @param[in] A pointer to the Target<T> + /// @param[in] The buffer + /// @return void + /// @post The contents of the buffer is replaced with the string + /// representation of the target + /// + template< TargetType T > + inline void toString(const Target<T>* i_target, char* i_buffer, size_t i_bsize) + { + snprintf(i_buffer, i_bsize, "Target 0x%lx/0x%x", i_target->get(), T); + } + + /// + /// @brief Get an enumerated target of a specific type + /// @tparam T The type of the target + /// @param[in] Ordinal representing the ordinal number of + /// the desired target + /// @return Target<T> the target requested + /// + template<TargetType T> + inline Target<T> getTarget(uint64_t Ordinal) + { + // For testing + return Target<T>(Ordinal); + } + + // Why has the been removed? For starters, the API name + // is probably wrong as it's already been confused with + // Target::getChildren(). And if I'm going to change it + // I really want to see if we need it. I'm still not + // clear on whether we're alloing this traversal or not. +#if 0 + /// + /// @brief Get the base target's children + /// @tparam T The type of the target + /// @return std::vector<Target<T> > a vector of present/functional + /// children + /// + template<TargetType T> + inline std::vector<Target<T> > getChildren() + { + // For testing + return {Target<T>(), Target<T>()}; + } +#endif + + /// + /// @brief Return the string interpretation of this target + /// @tparam T The type of the target + /// @tparam B The type of the buffer + /// @param[in] i_target Target<T> + /// @param[in] i_buffer buffer + /// @return void + /// @post The contents of the buffer is replaced with the string + /// representation of the target + /// + template<TargetType T, typename B> + inline void toString(const Target<T>& i_target, B& i_buffer); + + /// + /// @brief Check if the target is of a type, or in a type subset. + /// @tparam K the TargetType to check + /// @tparam T TargetType or TargetType composite to check against + /// @return True, iff K is a proper T + /// + template< TargetType K, TargetType T > + inline constexpr bool is_same(void) + { return (K & T) != 0; } + + +}; + +#endif diff --git a/src/ppe/hwpf/fapi/include/target_types.H b/src/ppe/hwpf/fapi/include/target_types.H new file mode 100755 index 0000000..926db45 --- /dev/null +++ b/src/ppe/hwpf/fapi/include/target_types.H @@ -0,0 +1,105 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/target_types.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file target_types.H + * @brief definitions for fapi2 target types + */ + +#ifndef __FAPI2_TARGET_TYPES__ +#define __FAPI2_TARGET_TYPES__ + +/// FAPI namespace +namespace fapi2 +{ + /// + /// @enum fapi::TargetType + /// @brief Types, kinds, of targets + /// @note TYPE_NONE is used to represent empty/NULL targets in lists + /// or tables. TYPE_ALL is used to pass targets to methods which + /// can act generally on any type of target + /// + /// Target Kind + enum TargetType + { + TARGET_TYPE_NONE = 0x00000000, ///< No type + TARGET_TYPE_SYSTEM = 0x00000001, ///< System type + TARGET_TYPE_DIMM = 0x00000002, ///< DIMM type + TARGET_TYPE_PROC_CHIP = 0x00000004, ///< Processor type + TARGET_TYPE_MEMBUF_CHIP = 0x00000008, ///< Membuf type + TARGET_TYPE_EX = 0x00000010, ///< Ex type + TARGET_TYPE_MBA = 0x00000020, ///< MBA type + TARGET_TYPE_MCS = 0x00000040, ///< MCS type + TARGET_TYPE_XBUS = 0x00000080, ///< XBUS type + TARGET_TYPE_ABUS = 0x00000100, ///< ABUS type + TARGET_TYPE_L4 = 0x00000200, ///< L4 type + TARGET_TYPE_CORE = 0x00000400, ///< Core type + TARGET_TYPE_EQ = 0x00000800, ///< EQ type + TARGET_TYPE_MCA = 0x00001000, ///< MCA type + TARGET_TYPE_MCBIST = 0x00002000, ///< MCBIST type + TARGET_TYPE_MIA = 0x00004000, ///< MIA type + TARGET_TYPE_MIS = 0x00008000, ///< MIS type + TARGET_TYPE_DMI = 0x00010000, ///< DMI type + TARGET_TYPE_OBUS = 0x00020000, ///< OBUS type + TARGET_TYPE_NV = 0x00040000, ///< NV bus type + TARGET_TYPE_SBE = 0x00080000, ///< SBE type + TARGET_TYPE_PPE = 0x00100000, ///< PPE type + TARGET_TYPE_PERV = 0x00200000, ///< Pervasive type + TARGET_TYPE_PEC = 0x00400000, ///< PEC type + TARGET_TYPE_PHB = 0x00800000, ///< PHB type + TARGET_TYPE_EL = 0x01000000, ///< L3/L2 Caches + + TARGET_TYPE_ALL = 0xFFFFFFFF, ///< Any/All types + + // Mappings to target types found in the error xml files + TARGET_TYPE_EX_CHIPLET = TARGET_TYPE_EX, + TARGET_TYPE_MBA_CHIPLET = TARGET_TYPE_MBA, + TARGET_TYPE_MCS_CHIPLET = TARGET_TYPE_MCS, + TARGET_TYPE_XBUS_ENDPOINT = TARGET_TYPE_XBUS, + TARGET_TYPE_ABUS_ENDPOINT = TARGET_TYPE_ABUS, + }; + + /// @cond + constexpr TargetType operator|(TargetType x, TargetType y) + { + return static_cast<TargetType>(static_cast<int>(x) | + static_cast<int>(y)); + } + + template<uint64_t V> + class bitCount { + public: + // Don't use enums, too hard to compare + static const uint8_t count = bitCount<(V >> 1)>::count + (V & 1); + }; + + template<> + class bitCount<0> { + public: + static const uint8_t count = 0; + }; + /// @endcond +}; + +#endif diff --git a/src/ppe/hwpf/fapi/include/utils.H b/src/ppe/hwpf/fapi/include/utils.H new file mode 100755 index 0000000..490e0b2 --- /dev/null +++ b/src/ppe/hwpf/fapi/include/utils.H @@ -0,0 +1,59 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/utils.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,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 */ +/** + * @file utils.H + * @brief Defines common fapi2 utilities + */ + +#ifndef FAPI2_UTILS_H_ +#define FAPI2_UTILS_H_ + +#include <stdint.h> +#include <return_code.H> +#include <error_info.H> + +namespace fapi2 +{ + /// + /// @brief Log an error. + /// + /// @param[in,out] io_rc Reference to ReturnCode (Any references to data and error + /// target are removed and rc value is set to success after + /// function ends.) + /// @param[in] i_sev Fapi error log severity defaulted to unrecoverable + /// @param[in] i_unitTestError - flag to log error which does not cause a unit + /// test to fail. + /// + /// @note This function is called from the ffdc collection classes and no longer + /// needs to be called directly. + /// @note Implemented by platform code + /// + void logError( + fapi2::ReturnCode & io_rc, + fapi2::errlSeverity_t i_sev = fapi2::FAPI2_ERRL_SEV_UNRECOVERABLE, + bool i_unitTestError = false ); +}; + +#endif // FAPI2_UTILS_H_ diff --git a/src/ppe/hwpf/fapi/include/variable_buffer.H b/src/ppe/hwpf/fapi/include/variable_buffer.H new file mode 100755 index 0000000..c0d637d --- /dev/null +++ b/src/ppe/hwpf/fapi/include/variable_buffer.H @@ -0,0 +1,663 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/include/variable_buffer.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file variable_buffer.H + * @brief definitions for fapi2 variable length buffers + */ + +#ifndef __FAPI2_VARIABLE_BUFFER__ +#define __FAPI2_VARIABLE_BUFFER__ + +#include <buffer_base.H> + +namespace fapi2 +{ + /// @brief Get a 32 bit mask quickly + // This is one of the main reasons we static_assert in the ctor's + // to ensure the unit_type is 32 bits. + inline uint32_t fast_mask32(int32_t i_pos, int32_t i_len) + { + // generates an arbitrary 32-bit mask using two operations, not too shabby + + static const uint32_t l_mask32[] = { + 0x00000000, + 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000, + 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000, + 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, + 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000, + 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, + 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, + 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0, + 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF, + }; + return l_mask32[i_len] >> i_pos; + } + + // + // General set a series of bits in the buffer. + // + + /// + /// @cond + /// @brief Internal bit inserting method. + /// @tparam unit_type The type of a unit of the arrays + /// @tparam bits_type The type of the bit counting values + /// @param[in] i_source The incoming data + /// @param[in] i_source_length The length in bits of the incoming data + /// @param[in] i_target The outgoing data + /// @param[in] i_target_length The length in bits of the outgoing data + /// @param[in] i_source_start_bit The starting bit location in the + /// incoming data + /// @param[in] i_target_start_bit The starting bit position in this + /// @param[in] i_length The length, in bits, the user wants copied. + /// + template<typename unit_type, typename bits_type> + inline fapi2::ReturnCode _insert(const unit_type* i_source, + bits_type i_source_length, + unit_type* i_target, + bits_type i_target_length, + bits_type i_source_start_bit, + bits_type i_target_start_bit, + bits_type i_length) + { + const bits_type bits_per_unit = fapi2::parameterTraits<unit_type>::bit_length; + + // tartgetStart is defaulted to the sizeof(target) - (sizeof(source) - i_source_start_bit) + // which makes this act like insert from right + if (i_target_start_bit == ~0) + { + i_target_start_bit = (i_target_length - (i_source_length - i_source_start_bit)); + } + + // len defaults to (sizeof(OT) * 8) - i_source_start_bit + if (i_length == ~0) + { + i_length = i_source_length - i_source_start_bit; + } + + // Check for overflow + if ((i_length + i_target_start_bit > i_target_length) || + (i_length + i_source_start_bit > i_source_length)) + { + return fapi2::FAPI2_RC_OVERFLOW; + } + + do + { + const bits_type src_idx = i_source_start_bit / bits_per_unit; + const bits_type trg_idx = i_target_start_bit / bits_per_unit; + + // "slop" = unaligned bits + const bits_type src_slop = i_source_start_bit % bits_per_unit; + const bits_type trg_slop = i_target_start_bit % bits_per_unit; + + // "cnt" = largest number of bits to be moved each pass + bits_type cnt = std::min(i_length, bits_per_unit); + cnt = std::min(cnt, bits_per_unit - src_slop); + cnt = std::min(cnt, bits_per_unit - trg_slop); + + // generate the source mask only once + bits_type mask = fast_mask32(src_slop, cnt); + + // read the source bits only once + bits_type src_bits = i_source[src_idx] & mask; + + // "shift" = amount of shifting needed for target alignment + int32_t shift = trg_slop - src_slop; + + // ideally (i << -1) would yield (i >> 1), but it + // doesn't, so we need an extra branch here + + if (shift < 0) + { + src_bits <<= -shift; + mask <<= -shift; + } + else + { + src_bits >>= shift; + mask >>= shift; + } + + // clear source '0' bits in the target + i_target[trg_idx] &= ~mask; + // set source '1' bits in the target + i_target[trg_idx] |= src_bits; + + i_source_start_bit += cnt; + i_target_start_bit += cnt; + + i_length -= cnt; + } while (0 < i_length); + + return fapi2::FAPI2_RC_SUCCESS; + } + /// @endcond + + /// @brief Class representing a FAPI variable_buffer. + /// @remark Variable buffers are buffers which can be variable in length + /// (and "odd sized.") These best represent the FAPI 1.X ecmdDataBuffer, + /// however they are implemented using the same template techniques + /// as the new fapi::buffer. + /// @note Variable buffers are not (presently) declared as std::bitset + /// as bitsets' size is fixed at runtime. It is not clear if this is + /// acceptable for variable_buffers at this time. + /// @note Variable buffers are not (presently) declared as std::vector<bool> + /// as it would need to be implemented separate from std::vector, and + /// it's not clear it would give us any real advantage. Howevever, its is + /// more likely this will become a std::vector<bool> than a std::bitset. + class variable_buffer : public buffer_base<bits_container> + { + + public: + + /// + /// @brief Variable buffer constructor + /// @param[in] i_value number of *bits* (sizeof(uint_type) * 8) + /// needed. + variable_buffer(bits_type i_value = 0); + + /// + /// @brief Variable buffer list constructor + /// @param[in] i_value an initializer list to initialize the container. + /// + variable_buffer(const std::initializer_list<unit_type>& i_value); + + /// @name Bit/Word Manipulation Functions + ///@{ + + /// + /// @brief Return the length of the buffer in bits + /// @return Length in bits + /// + inline uint32_t getBitLength(void) const + { return iv_perceived_bit_length; } + + /// + /// @brief Return the length of the buffer in OT units + /// @return Length in OT units rounded up + /// @tparam OT the type to get the length of. For example, if one + /// wanted the length in double words, OT would be uint64_t + /// (getLength<uint64_t>().) Similarly, to get the length in words, + /// getLength<uin32_t>(). + /// + template< typename OT > + inline uint32_t getLength(void) const + { + static const uint32_t bits_in_ot = sizeof(OT) * 8; + return (getBitLength() + (bits_in_ot - 1)) / bits_in_ot; + } + + /// + /// @brief Set a bit in the buffer + /// @param[in] i_bit the bit number to set. + /// @note 0 is left-most + /// @return FAPI2_RC_SUCCESS if OK + /// + inline fapi2::ReturnCode setBit(const bits_type& i_bit) + { + const bits_type index = i_bit / bits_per_unit; + + if (index > iv_data.size()) + { + return FAPI2_RC_INVALID_PARAMETER; + } + + iv_data[index] |= + unit_type(1) << (bits_per_unit - 1) - + (i_bit - (index * bits_per_unit)); + + return FAPI2_RC_SUCCESS; + } + + /// + /// @brief Clear a bit in buffer + /// @tparam SB Start bit in buffer to clear. + /// @tparam L Number of consecutive bits from start bit to + /// clear + /// @return FAPI2_RC_SUCCESS on success + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template< bits_type SB, bits_type L > + fapi2::ReturnCode clearBit(void); + + /// + /// @brief Invert bit + /// @tparam SB Start bit in buffer to invert. + /// @tparam L Number of consecutive bits from start bit to + /// invert, defaults to 1 + /// @return FAPI2_RC_SUCCESS on success + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template< bits_type SB, bits_type L = 1 > + fapi2::ReturnCode flipBit(void); + + /// + /// @brief Get the value of a bit in the buffer + /// @tparam B Bit in buffer to get. + /// @return true/1 if bit is on, false/0 if bit is off + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template< bits_type B > + inline bool getBit(void) const + { + const bits_type index = B / bits_per_unit; + const unit_type mask = unit_type(1) << (bits_per_unit - 1) - (B - (index * bits_per_unit)); + return iv_data[index] & mask; + } + + /// + /// @brief Test if multiple bits are set + /// @tparam SB Start bit in buffer to test. + /// @tparam L Number of consecutive bits from start bit to + /// test, defaults to 1 + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// @return true if all bits in range are set - false if any + /// bit is clear + /// + template< bits_type SB, bits_type L = 1 > + bool isBitSet(void) const; + + /// + /// @brief Test if multiple bits are clear + /// @tparam SB Start bit in buffer to test. + /// @tparam L Number of consecutive bits from start bit to + /// test, defaults to 1 + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// @return true if bit is clear - false if bit is set + /// + template< bits_type SB, bits_type L = 1 > + bool isBitClear(void) const; + + /// + /// @brief Count number of bits set in a range + /// @tparam SB Start bit in buffer to test. + /// @tparam L Number of consecutive bits from start bit to + /// test, defaults to 1 + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// @return Number of bits set in range + /// + template< bits_type SB, bits_type L = 1 > + bits_type getNumBitsSet(void) const; + + ///@} + + /// @name Buffer Manipulation Functions + ///@{ + + // Note: Many (all?) of these are not needed and the compiler complains + // as the cast to T yields a better operator. There are here mainly for + // documenation purposes. + + /// + /// @brief operator>>() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator>>(bits_type i_shiftnum); +#endif + + /// + /// @brief operator<<() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator<<(bits_type i_shiftnum); +#endif + + /// + /// @brief operator+() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator+(const T& rhs); +#endif + + /// + /// @brief operator+=() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator+=(const T& rhs); +#endif + + /// + /// @brief operator|=() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator|=(const T& rhs); +#endif + + /// + /// @brief operator&=() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator&=(const T& rhs); +#endif + + /// + /// @brief operator|() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator|(const T& rhs); +#endif + + /// + /// @brief operator&() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator&(const T& rhs); +#endif + + /// + /// @brief operator^=() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator^=(const T& rhs); +#endif + + /// + /// @brief operator!=() + /// +#ifdef DOXYGEN + bool operator!=(const T& rhs) const; +#endif + + /// + /// @brief operator==() + /// @return true if and only if lhs == rhs + /// + inline bool operator==(const fapi2::bits_container& rhs) const + { + if (&iv_data == &rhs) + { + return true; + } + + return iv_data == rhs; + } + + /// + /// @brief Copy part of an element into the DataBuffer + /// @param[in] i_data OT value to copy into DataBuffer + /// @param[in] i_targetStart The position in this where the copy starts + /// @param[in] i_len How many bits to copy + /// @param[in] i_sourceStart The start positon in i_data, defaults to 0 + /// @return FAPI2_RC_SUCCESS on success, FAPi2_RC_OVERFLOW otherwise + /// + template<typename OT> + fapi2::ReturnCode insert(const OT& i_data, + bits_type i_targetStart = 0, + bits_type i_len = ~0, + bits_type i_sourceStart = 0); + + /// + /// @brief Copy in a right aligned (decimal) element + /// @param[in] i_data the incoming data + /// - data is taken right aligned + /// @param[in] i_targetStart The starting bit position in this + /// - Defaultst to 0 + /// @param[in] i_len The length, in bits, the user wants copied. + /// - Defaults to all of the bits in the source which fit + /// @return FAPI2_RC_SUCCESS on success, FAPI2_RC_OVERFLOW otherwise + /// + template<typename OT> + fapi2::ReturnCode insertFromRight(const OT& i_data, + bits_type i_targetStart = 0, + bits_type i_len = ~0); + + /// + /// @brief Copy data from this buffer into an OT + /// @tparam OT the type of the outgoing data + /// @param[out] o_out OT to copy into - data is placed left aligned + /// @param[in] i_start Start bit to copy from - defaults to 0 + /// @param[in] i_len Length of bits to copy - defaults to filling o_out + /// @return FAPI2_RC_SUCCESS on success + /// + template< typename OT > + fapi2::ReturnCode extract(OT& o_out, + bits_type i_start = 0, + bits_type i_len = ~0) const; + + /// + /// @brief Copy data from this buffer into an OT and right justify + /// @tparam OT the type of the outgoing data + /// @param[out] o_out OT to copy into - data is placed right aligned + /// @param[in] i_start Start bit to copy from - defaults to 0 + /// @param[in] i_len Length of bits to copy - defaults to filling o_out + /// @return FAPI2_RC_SUCCESS on success + /// + template< typename OT > + fapi2::ReturnCode extractToRight(OT& o_out, + bits_type i_start = 0, + bits_type i_len = ~0) const; + ///@} + + private: + // Just shorthand ... + static const bits_type bits_per_unit = + bufferTraits<bits_container>::bits_per_unit; + + // The number of bits the user asked for. The actual size of the + // container might be larger. + bits_type iv_perceived_bit_length; + + /// + /// @brief Internal bit extraction method. + /// @tparam OT The type of the destination + /// @param[in] i_start The starting bit position in this + /// @param[in] i_count The length, in bits, the user wants copied. + /// @param[out] o_dest Where to put the data + /// + template< typename OT > + fapi2::ReturnCode _extract(bits_type i_start, + bits_type i_count, + OT* o_dest) const; + + /// + /// @brief Internal insertFromRight + /// @param[in] i_data, the incoming data + /// @param[in] i_data_length The length in bits of the incoming data + /// @param[in] i_target_start_bit The starting bit position in this + /// @param[in] i_length The length, in bits, the user wants copied. + /// + template<typename OT> + fapi2::ReturnCode _insertFromRight(const OT& i_data, + bits_type i_data_length, + bits_type i_targetStart, + bits_type i_len); + + }; + + inline variable_buffer:: + variable_buffer(bits_type i_value): + buffer_base(i_value), + iv_perceived_bit_length(i_value) + { + static_assert(std::is_same<unit_type, uint32_t>::value, + "code currently needs unit_type to be a unit32_t"); + } + + inline variable_buffer:: + variable_buffer(const std::initializer_list<unit_type>& i_value): + buffer_base(i_value), + iv_perceived_bit_length(i_value.size() * sizeof(unit_type) * 8) + { + static_assert(std::is_same<unit_type, uint32_t>::value, + "code currently needs unit_type to be a unit32_t"); + } + + + + /// @cond + // + // Generic insert + // + template<typename OT> + inline fapi2::ReturnCode variable_buffer::insert(const OT& i_source, + bits_type i_targetStart, + bits_type i_len, + bits_type i_sourceStart) + { + return _insert((unit_type*)(&i_source), parameterTraits<OT>::bit_length, + &(iv_data[0]), getBitLength(), + i_sourceStart, i_targetStart, i_len); + } + + // + // Insert another variable_bufer + // + template<> + inline fapi2::ReturnCode variable_buffer::insert( + const variable_buffer& i_data, + bits_type i_targetStart, + bits_type i_len, + bits_type i_sourceStart) + { + return _insert((unit_type*)&(i_data()[0]), i_data.getBitLength(), + &(iv_data[0]), getBitLength(), + i_sourceStart, i_targetStart, i_len); + } + + // + // Generic insert from right + // + template<typename OT> + inline fapi2::ReturnCode variable_buffer::insertFromRight( + const OT& i_data, + bits_type i_targetStart, + bits_type i_len) + { + _insertFromRight(i_data, parameterTraits<OT>::bit_length, i_targetStart, i_len); + } + + // + // variable_buffer insert from right + // + template<> + inline fapi2::ReturnCode variable_buffer::insertFromRight( + const variable_buffer& i_data, + bits_type i_targetStart, + bits_type i_len) + { + const bits_type bit_length_of_source = i_data.getBitLength(); + _insertFromRight(i_data, bit_length_of_source, i_targetStart, i_len); + } + + + + + // + // Generic extract. Extract is an insert with the arguments reversed. + // + template<typename OT> + inline fapi2::ReturnCode variable_buffer::extract( + OT& i_data, + bits_type i_start, + bits_type i_len) const + { + // Needed to trick the compiler into matching the template below + const bits_type max_length = parameterTraits<OT>::bit_length; + + // If thy didn't pass an i_len, assume they want all the data + // which will fit. + if (i_len == ~0) + { + i_len = max_length; + } + + return _insert((container_unit*)&iv_data[0], getBitLength(), + &i_data, max_length, + i_start, 0U, i_len); + } + + // + // Extract in to another variable_bufer + // + template<> + inline fapi2::ReturnCode variable_buffer::extract( + variable_buffer& i_data, + bits_type i_start, + bits_type i_len) const + { + // If thy didn't pass an i_len, assume they want all the data + // which will fit. + if (i_len == ~0) + { + i_len = i_data.getBitLength(); + } + return _insert((container_unit*)&iv_data[0], getBitLength(), + &(i_data()[0]), i_data.getBitLength(), + i_start, 0U, i_len); + } + + + + template<typename OT> + inline fapi2::ReturnCode variable_buffer::_insertFromRight( + const OT& i_data, + bits_type i_data_length, + bits_type i_targetStart, + bits_type i_len) + { + // If they didn't pass in a length, assume they want all the i_data + // which will fit. + if( i_len == ~0 ) + { + // The longest the length can be is the length of the data + // This is the miniumum of the length of the data or the + // number of available bits + i_len = std::min(i_data_length, getBitLength() - i_targetStart); + } + + // Source start is the length, counted from the right + return insert(i_data, i_targetStart, i_len, i_data_length - i_len); + } + + // + // Invalid specializations of set + // + /// @cond + // Sepcialize the variable_buffer version to to "undefined" so the + // linker complains loudly if anyone calls it. +#if 0 + template<> + inline fapi2::ReturnCode buffer_base::set( + const variable_buffer& i_value, + bits_type i_offset); +#endif + /// @endcond +}; + + +#endif diff --git a/src/ppe/hwpf/fapi/src/error_info.C b/src/ppe/hwpf/fapi/src/error_info.C new file mode 100755 index 0000000..df4888e --- /dev/null +++ b/src/ppe/hwpf/fapi/src/error_info.C @@ -0,0 +1,412 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/src/error_info.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/** + * @file error_info.C + * @brief Implements the error information classes + */ + +#include <stdint.h> +#include <string.h> +#include <plat_trace.H> +#include <error_info.H> +#include <buffer.H> + +namespace fapi2 +{ + /// + /// @brief Constructor + /// + /// @param[in] i_ffdcId FFDC Identifier (used to decode FFDC) + /// @param[in] i_pFfdc Pointer to the FFDC to copy + /// @param[in] i_size Size of the FFDC to copy + /// + ErrorInfoFfdc::ErrorInfoFfdc(const uint32_t i_ffdcId, + const void* i_pFfdc, + const uint32_t i_size): + iv_ffdcId(i_ffdcId), + iv_size(i_size) + { + iv_pFfdc = std::shared_ptr<uint8_t>(new uint8_t[i_size]()); + + // If they passed us a NULL pointer they want to fill + // in the data themselves later. + if (i_pFfdc != nullptr) + { + memcpy(iv_pFfdc.get(), i_pFfdc, i_size); + } + } + + /// + /// @brief Constructor. + /// + /// @param[in] i_hw Hardware to callout + /// @param[in] i_calloutPriority Priority of callout + /// @param[in] i_refTarget Reference to reference target + /// + ErrorInfoHwCallout::ErrorInfoHwCallout( + const HwCallouts::HwCallout i_hw, + const CalloutPriorities::CalloutPriority i_calloutPriority, + const Target<TARGET_TYPE_ALL> & i_refTarget): + iv_hw(i_hw), + iv_calloutPriority(i_calloutPriority), + iv_refTarget(i_refTarget) + {} + + /// + /// @brief Constructor. + /// + /// @param[in] i_procedure Procedure to callout + /// @param[in] i_calloutPriority Priority of callout + /// + ErrorInfoProcedureCallout::ErrorInfoProcedureCallout( + const ProcedureCallouts::ProcedureCallout i_procedure, + const CalloutPriorities::CalloutPriority i_calloutPriority): + iv_procedure(i_procedure), + iv_calloutPriority(i_calloutPriority) + {} + + /// + /// @brief Constructor. + /// + /// @param[in] i_target1 Reference to target on one end of the bus + /// @param[in] i_target2 Reference to target on other end of the bus + /// @param[in] i_calloutPriority Priority of callout + /// + ErrorInfoBusCallout::ErrorInfoBusCallout( + const Target<TARGET_TYPE_ALL> & i_target1, + const Target<TARGET_TYPE_ALL> & i_target2, + const CalloutPriorities::CalloutPriority i_calloutPriority): + iv_target1(i_target1), + iv_target2(i_target2), + iv_calloutPriority(i_calloutPriority) + {} + + /// + /// @brief Constructor. + /// + /// @param[in] i_target Reference to the target to c/d/g + /// @param[in] i_callout True if Target should be called out + /// @param[in] i_deconfigure True if Target should be deconfigured + /// @param[in] i_gard True if Target should be GARDed + /// @param[in] i_priority The priority of any callout + /// + ErrorInfoCDG::ErrorInfoCDG( + const Target<TARGET_TYPE_ALL> & i_target, + const bool i_callout, + const bool i_deconfigure, + const bool i_gard, + const CalloutPriorities::CalloutPriority i_priority): + iv_target(i_target), + iv_callout(i_callout), + iv_deconfigure(i_deconfigure), + iv_gard(i_gard), + iv_calloutPriority(i_priority) + {} + + /// + /// @brief Constructor. + /// + /// @param[in] i_parent Reference to the parent target + /// @oaram[in] i_childType Child target type to c/d/g + /// @param[in] i_callout True if Target should be called out + /// @param[in] i_deconfigure True if Target should be deconfigured + /// @param[in] i_gard True if Target should be GARDed + /// @param[in] i_priority The priority of any callout + /// @param[in] i_childPort Child Port + /// For DIMM children, the MBA port number + /// @param[in] i_childNum Child Number + /// For DIMM children, the dimm socket number + /// For Chip children, the chip position + /// For Chiplet children, the chiplet unit pos + /// + ErrorInfoChildrenCDG::ErrorInfoChildrenCDG( + const Target<TARGET_TYPE_ALL> & i_parentChip, + const TargetType i_childType, + const bool i_callout, + const bool i_deconfigure, + const bool i_gard, + const CalloutPriorities::CalloutPriority i_priority, + const uint8_t i_childPort, const uint8_t i_childNum): + iv_parent(i_parentChip), + iv_childType(i_childType), + iv_callout(i_callout), + iv_calloutPriority(i_priority), + iv_deconfigure(i_deconfigure), + iv_gard(i_gard), + iv_childPort(i_childPort), + iv_childNumber(i_childNum) + {} + + /// + /// @brief Constructor. + /// + /// @param[in] i_trace + /// + ErrorInfoCollectTrace::ErrorInfoCollectTrace( + CollectTraces::CollectTrace i_traceId): + iv_eiTraceId(i_traceId) + {} + + + /// + /// @brief Collect target, buffer or generic FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryFfdc::addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_objects) const + { + // "variable buffer ffdc not yet implemented"); + assert(iv_ffdcSize != EI_FFDC_SIZE_VBUF); + + switch(iv_ffdcSize) + { + case EI_FFDC_SIZE_BUF: + { + const buffer<uint64_t>* object = + static_cast<const buffer<uint64_t>*>(i_objects[iv_ffdcObjIndex]); + + i_info->iv_ffdcs.push_back(std::shared_ptr<ErrorInfoFfdc>( + new ErrorInfoFfdc(iv_ffdcId, object, + sizeof(object)))); + + FAPI_DBG("addErrorInfo: Adding buffer id: 0x%x size: %lu buf: 0x%lx", + iv_ffdcId, sizeof(object), uint64_t(*object)); + } + break; + + case EI_FFDC_SIZE_TARGET: + { + Target<TARGET_TYPE_ALL> object = + *(static_cast<const Target<TARGET_TYPE_ALL>*> + (i_objects[iv_ffdcObjIndex])); + + // Allocate an ErrorInfoFfdc but don't copy anything in to it. + // We can copy the target string once if we copy directly into + // the error info + ErrorInfoFfdc* e = + new ErrorInfoFfdc(iv_ffdcId, nullptr, MAX_ECMD_STRING_LEN); + + toString(object, static_cast<char*>(e->getData()), + MAX_ECMD_STRING_LEN); + i_info->iv_ffdcs.push_back(std::shared_ptr<ErrorInfoFfdc>(e)); + + FAPI_DBG("addErrorInfo: Adding target ffdc id: 0x%x %s", + iv_ffdcId, static_cast<char*>(e->getData())); + } + break; + + default: + i_info->iv_ffdcs.push_back(std::shared_ptr<ErrorInfoFfdc>( + new ErrorInfoFfdc( + iv_ffdcId, + i_objects[iv_ffdcObjIndex], + iv_ffdcSize))); + FAPI_DBG("addErrorInfo: Adding ffdc id 0x%x size: %d", + iv_ffdcId, iv_ffdcSize); + break; + + }; + + return; + } + + /// + /// @brief Collect h/w callout FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryHwCallout::addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const + { + // If the index is 0xFF, we use an empty target. Otherwise the + // target is taken from the object arrary with the given index. + const fapi2::Target<TARGET_TYPE_ALL> target = + iv_refObjIndex == 0xFF ? + fapi2::Target<TARGET_TYPE_ALL>() : + *(static_cast<const fapi2::Target<TARGET_TYPE_ALL>*> + (i_object[iv_refObjIndex])); + + ErrorInfoHwCallout* ei = new ErrorInfoHwCallout( + static_cast<HwCallouts::HwCallout>(iv_hw), + static_cast<CalloutPriorities::CalloutPriority>(iv_calloutPriority), + target); + + FAPI_DBG("addErrorInfo: Adding hw callout target: 0x%lx hw: %d, pri: %d", + ei->iv_refTarget.get(), ei->iv_hw, ei->iv_calloutPriority); + + i_info->iv_hwCallouts.push_back(std::shared_ptr<ErrorInfoHwCallout>(ei)); + } + + /// + /// @brief Collect proc callout FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryProcCallout::addErrorInfo( + std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const + { + ErrorInfoProcedureCallout* ei = new ErrorInfoProcedureCallout( + static_cast<ProcedureCallouts::ProcedureCallout>(iv_procedure), + static_cast<CalloutPriorities::CalloutPriority>(iv_calloutPriority)); + + // Add the ErrorInfo + FAPI_DBG("addErrorInfo: Adding proc callout, proc: %d, pri: %d", + ei->iv_procedure, ei->iv_calloutPriority); + + i_info->iv_procedureCallouts.push_back( + std::shared_ptr<ErrorInfoProcedureCallout>(ei)); + } + + /// + /// @brief Collect bus callout FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryBusCallout::addErrorInfo( + std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const + { + // We need to add a procedure callout as well as a bus callout + ErrorInfoEntryProcCallout(ProcedureCallouts::BUS_CALLOUT, + iv_calloutPriority).addErrorInfo(i_info, + i_object); + + // Now add our bus callout, but drop the priority by one. + ErrorInfoBusCallout* ei = new ErrorInfoBusCallout( + // First target + *(static_cast<const fapi2::Target<TARGET_TYPE_ALL>*> + (i_object[iv_endpoint1ObjIndex])), + + // Second target + *(static_cast<const fapi2::Target<TARGET_TYPE_ALL>*> + (i_object[iv_endpoint2ObjIndex])), + + // Priority, one lower. + (iv_calloutPriority == CalloutPriorities::HIGH) ? + CalloutPriorities::MEDIUM : CalloutPriorities::LOW); + + FAPI_DBG("addErrorInfo: Adding bus callout t1: 0x%lx t2: 0x%lx, pri: %d", + ei->iv_target1.get(), ei->iv_target2.get(), + ei->iv_calloutPriority); + + i_info->iv_busCallouts.push_back( + std::shared_ptr<ErrorInfoBusCallout>(ei)); + } + + /// + /// @brief Collect h/w target cdg FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryTargetCDG::addErrorInfo( + std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const + { + ErrorInfoCDG* ei = new + ErrorInfoCDG( + *(static_cast<const fapi2::Target<TARGET_TYPE_ALL>*> + (i_object[iv_targetObjIndex])), + iv_callout, + iv_deconfigure, + iv_gard, + static_cast<CalloutPriorities::CalloutPriority> + (iv_calloutPriority) + ); + + FAPI_DBG("addErrorInfo: Adding target 0x%lx cdg (%d:%d:%d), pri: %d", + ei->iv_target.get(), + ei->iv_callout, ei->iv_deconfigure, + ei->iv_gard, ei->iv_calloutPriority); + + // Add the ErrorInfo + i_info->iv_CDGs.push_back(std::shared_ptr<ErrorInfoCDG>(ei)); + } + + /// + /// @brief Collect h/w children cdg FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryChildrenCDG::addErrorInfo( + std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const + { + ErrorInfoChildrenCDG* ei = new ErrorInfoChildrenCDG( + *(static_cast<const fapi2::Target<TARGET_TYPE_ALL>*> + (i_object[iv_parentObjIndex])), + static_cast<fapi2::TargetType>(iv_childType), + iv_callout, + iv_deconfigure, + iv_gard, + static_cast<CalloutPriorities::CalloutPriority> + (iv_calloutPriority), + iv_childPort, + iv_childNumber); + + FAPI_DBG("addErrorInfo: Adding children cdg (%d:%d:%d), type:" + " 0x%08x, pri: %d", + ei->iv_callout, ei->iv_deconfigure, ei->iv_gard, + ei->iv_childType, ei->iv_calloutPriority); + + // Add the ErrorInfo + i_info->iv_childrenCDGs.push_back( + std::shared_ptr<ErrorInfoChildrenCDG>(ei)); + } + + /// + /// @brief Collect trace information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryCollectTrace::addErrorInfo( + std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const + { + ErrorInfoCollectTrace* ei = new ErrorInfoCollectTrace( + static_cast<CollectTraces::CollectTrace>(iv_eieTraceId)); + + FAPI_DBG("addErrorInfo: Adding trace: 0x%x", ei->iv_eiTraceId); + + // Add the ErrorInfo + i_info->iv_traces.push_back(std::shared_ptr<ErrorInfoCollectTrace>(ei)); + } + +}; diff --git a/src/ppe/hwpf/fapi/src/ffdc.C b/src/ppe/hwpf/fapi/src/ffdc.C new file mode 100755 index 0000000..9b7504d --- /dev/null +++ b/src/ppe/hwpf/fapi/src/ffdc.C @@ -0,0 +1,59 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/src/ffdc.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/** + * @file ffdc.C + * @brief Implements the FirstFailureData class + */ + +#include <plat_trace.H> +#include <ffdc.H> +#include <error_info.H> + +namespace fapi2 +{ + + /// + /// @brief Add error information to this ffdc object + /// @param[in] A pointer to a list of objects + /// @param[in] A pointer to the list of entries + /// @param[in] The count of how many entries there are + /// @return void + /// + template<> + void FirstFailureData<ReturnCode>::addErrorInfo( + const void* const* i_pObjects, + const ErrorInfoEntry* i_pEntries, + const uint8_t i_count) + { + FAPI_DBG("%d entries", i_count); + for (uint32_t i = 0; i < i_count; i++) + { + i_pEntries[i].addErrorInfo(iv_info, i_pObjects); + } + } + + + +}; diff --git a/src/ppe/hwpf/fapi/src/plat_utils.C b/src/ppe/hwpf/fapi/src/plat_utils.C new file mode 100755 index 0000000..aafc35f --- /dev/null +++ b/src/ppe/hwpf/fapi/src/plat_utils.C @@ -0,0 +1,119 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/fapi/src/plat_utils.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/** + * @file plat_utils.C + * @brief Implements fapi2 common utilities + */ + +#include <stdint.h> +#include <plat_trace.H> +#include <return_code.H> +#include <error_info.H> + +namespace fapi2 +{ + /// + /// @brief Log an error. + /// + void logError( + fapi2::ReturnCode & io_rc, + fapi2::errlSeverity_t i_sev = fapi2::FAPI2_ERRL_SEV_UNRECOVERABLE, + bool i_unitTestError = false ) + { + FAPI_DBG("logging 0x%lx.", uint64_t(io_rc)); + + // Iterate over the vectors and output what is in them. + const ErrorInfo* ei = io_rc.getErrorInfo(); + + FAPI_DBG("ffdcs: %lu", ei->iv_ffdcs.size()); + for( auto i = ei->iv_ffdcs.begin(); i != ei->iv_ffdcs.end(); ++i ) + { + uint32_t sz; + (*i)->getData(sz); + FAPI_DBG("\tid: 0x%x size %d", (*i)->getFfdcId(), sz); + } + + FAPI_DBG("hwCallouts: %lu", ei->iv_hwCallouts.size()); + for( auto i = ei->iv_hwCallouts.begin(); i != ei->iv_hwCallouts.end(); + ++i ) + { + FAPI_DBG("\thw: %d pri %d target: 0x%lx", + (*i)->iv_hw, (*i)->iv_calloutPriority, + (*i)->iv_refTarget.get()); + } + + FAPI_DBG("procedureCallouts: %lu", ei->iv_procedureCallouts.size()); + for( auto i = ei->iv_procedureCallouts.begin(); + i != ei->iv_procedureCallouts.end(); ++i ) + { + FAPI_DBG("\tprocedure: %d pri %d", + (*i)->iv_procedure, (*i)->iv_calloutPriority); + } + + FAPI_DBG("busCallouts: %lu", ei->iv_busCallouts.size()); + for( auto i = ei->iv_busCallouts.begin(); i != ei->iv_busCallouts.end(); + ++i ) + { + FAPI_DBG("\tbus: t1: 0x%lx t2: 0x%lx pri: %d", + (*i)->iv_target1.get(), (*i)->iv_target2.get(), + (*i)->iv_calloutPriority); + } + + + FAPI_DBG("cdgs: %lu", ei->iv_CDGs.size()); + for( auto i = ei->iv_CDGs.begin(); i != ei->iv_CDGs.end(); ++i ) + { + FAPI_DBG("\ttarget: 0x%lx co: %d dc: %d gard: %d pri: %d", + (*i)->iv_target.get(), + (*i)->iv_callout, + (*i)->iv_deconfigure, + (*i)->iv_gard, + (*i)->iv_calloutPriority); + + } + + FAPI_DBG("childrenCDGs: %lu", ei->iv_childrenCDGs.size()); + for( auto i = ei->iv_childrenCDGs.begin(); + i != ei->iv_childrenCDGs.end(); ++i ) + { + FAPI_DBG("\tchildren: parent 0x%lx co: %d dc: %d gard: %d pri: %d", + (*i)->iv_parent.get(), + (*i)->iv_callout, + (*i)->iv_deconfigure, + (*i)->iv_gard, + (*i)->iv_calloutPriority); + } + + FAPI_DBG("traces: %lu", ei->iv_traces.size()); + for( auto i = ei->iv_traces.begin(); i != ei->iv_traces.end(); ++i ) + { + FAPI_DBG("\ttraces: 0x%x", (*i)->iv_eiTraceId); + } + + // Release the ffdc information now that we're done with it. + io_rc.forgetData(); + + } +}; diff --git a/src/ppe/hwpf/fapi/tools/parseErrorInfo.pl b/src/ppe/hwpf/fapi/tools/parseErrorInfo.pl new file mode 100755 index 0000000..ba2fefb --- /dev/null +++ b/src/ppe/hwpf/fapi/tools/parseErrorInfo.pl @@ -0,0 +1,1479 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/hwpf/fapi/tools/parseErrorInfo.pl $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 2011,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: fapiParseErrorInfo.pl,v 1.30 2014/07/25 00:36:41 jmcgill Exp $ +# Purpose: This perl script will parse HWP Error XML files and create required +# FAPI code. +# +# Author: CamVan Nguyen and Mike Jones +# Reworked for fapi2/P9 +# +# Usage: +# fapiParseErrorInfo.pl <output dir> <filename1> <filename2> ... + +use strict; + +#------------------------------------------------------------------------------ +# Set PREFERRED_PARSER to XML::Parser. Otherwise it uses XML::SAX which contains +# bugs that result in XML parse errors that can be fixed by adjusting white- +# space (i.e. parse errors that do not make sense). +#------------------------------------------------------------------------------ +$XML::Simple::PREFERRED_PARSER = 'XML::Parser'; + +#------------------------------------------------------------------------------ +# Specify perl modules to use +#------------------------------------------------------------------------------ +use Digest::MD5 qw(md5_hex); +use XML::Simple; +my $xml = new XML::Simple (KeyAttr=>[]); + +# Uncomment to enable debug output +use Data::Dumper; +use Getopt::Long; + +my $target_ffdc_type = "fapi2::Target<fapi2::TARGET_TYPE_ALL>"; +my $buffer_ffdc_type = "fapi2::buffer"; +my $variable_buffer_ffdc_type = "fapi2::variable_buffer"; +my $ffdc_type = "fapi2::ffdc_t"; + +# We want to keep the signatures for the ffdc gathering hwp so that +# we can create members of the proper types for the ffdc classes. +my %signatures = ("proc_extract_pore_halt_ffdc" => ["por_base_state", + "por_halt_type_t", + "por_ffdc_offset_t"], + "hwpTestFfdc1" => [$target_ffdc_type], + "proc_extract_pore_base_ffdc" => ["por_base_state", "por_sbe_base_state"], + "proc_tp_collect_dbg_data" => [$target_ffdc_type], + ); + +# There are some names used in the XML files which exist in either +# c++ keywords (case, for example) or macros (DOMAIN). The one's which +# cause problems and need to be changed are here. +# +# DOMAIN is defined to 1 in math.h +my %mangle_names = ("DOMAIN" => "FAPI2_DOMAIN"); + +# A list of deprecated elements. These will report messages to the +# user, and not define anything. They have not been found to be used, +# but that doesn't mean they're not ... +my %deprecated = ("RC_PROCPM_PMCINIT_TIMEOUT" => "CHIP_IN_ERROR is defined as a callout procedure"); + +#------------------------------------------------------------------------------ +# Print Command Line Help +#------------------------------------------------------------------------------ +my $arg_empty_ffdc = undef; +my $arg_output_dir = undef; +my $arg_use_variable_buffers = undef; + +# Get the options from the command line - the rest of @ARGV will +# be filenames +GetOptions("empty-ffdc-classes" => \$arg_empty_ffdc, + "output-dir=s" => \$arg_output_dir, + "use-variable-buffers" => \$arg_use_variable_buffers); + +my $numArgs = $#ARGV + 1; +if (($numArgs < 1) || ($arg_output_dir eq undef)) +{ + print ("Usage: parseErrorInfo.pl [--empty-ffdc-classes] [--use-variable-buffers] --output-dir=<output dir> <filename1> <filename2> ...\n"); + print (" This perl script will parse HWP Error XML files and creates\n"); + print (" the following files:\n"); + print (" - hwp_return_codes.H. HwpReturnCode enumeration (HWP generated errors)\n"); + print (" - hwp_error_info.H. Error information (used by FAPI_SET_HWP_ERROR\n"); + print (" when a HWP generates an error)\n"); + print (" - collect_reg_ffdc.C. Function to collect register FFDC\n"); + print (" - set_sbe_error.H. Macro to create an SBE error\n"); + print (" The --empty-ffdc-classes option is for platforms which don't collect ffdc.\n"); + exit(1); +} + +#------------------------------------------------------------------------------ +# Hashes containing error names/enum-values +#------------------------------------------------------------------------------ +my %errNameToValueHash; +my %errValuePresentHash; + +#------------------------------------------------------------------------------ +# Hashes containing ffdc names/enum-values +#------------------------------------------------------------------------------ +my %ffdcNameToValueHash; +my %ffdcValuePresentHash; + +#------------------------------------------------------------------------------ +# Subroutine that checks if an entry exists in an array. If it doesn't exist +# then it is added. The index of the entry within the array is returned +#------------------------------------------------------------------------------ +sub addEntryToArray +{ + my ($arrayref, $entry ) = @_; + + my $match = 0; + my $index = 0; + + foreach my $element (@$arrayref) + { + if ($element eq $entry) + { + $match = 1; + last; + } + else + { + $index++; + } + } + + if (!($match)) + { + push(@$arrayref, $entry); + } + + return $index; +} + +#------------------------------------------------------------------------------ +# Subroutine that figures out an error enum value from an error name and stores +# it in global hashes +#------------------------------------------------------------------------------ +sub setErrorEnumValue +{ + my $name = $_[0]; + + #-------------------------------------------------------------------------- + # Check that the error name is not a duplicate + #-------------------------------------------------------------------------- + if (exists($errNameToValueHash{$name})) + { + # Two different errors with the same name! + print ("fapiParseErrorInfo.pl ERROR. Duplicate error name ", $name, "\n"); + exit(1); + } + + #-------------------------------------------------------------------------- + # Figure out the error enum-value. This is a hash value generated from + # the error name. A hash is used for Cronus so that if a HWP is not + # recompiled against a new eCMD/Cronus version where the errors have + # changed then there will not be a mismatch in error values. + # This is a 24bit hash value because FAPI has a requirement that the + # top byte of the 32 bit error value be zero to store flags indicating + # the creator of the error + #-------------------------------------------------------------------------- + my $errHash128Bit = md5_hex($name); + my $errHash24Bit = substr($errHash128Bit, 0, 6); + + #-------------------------------------------------------------------------- + # Check that the error enum-value is not a duplicate + #-------------------------------------------------------------------------- + if (exists($errValuePresentHash{$errHash24Bit})) + { + # Two different errors generate the same hash-value! + print ("fapiParseAttributeInfo.pl ERROR. Duplicate error hash value\n"); + exit(1); + } + + #-------------------------------------------------------------------------- + # Update the hashes with the error name and ID + #-------------------------------------------------------------------------- + $errValuePresentHash{$errHash24Bit} = 1; + $errNameToValueHash{$name} = $errHash24Bit; +} + +#------------------------------------------------------------------------------ +# Subroutine that figures out an FFDC ID value from an FFDC name and stores it +# in global hashes for use when creating the enumeration of FFDC IDs +#------------------------------------------------------------------------------ +sub setFfdcIdValue +{ + my $name = $_[0]; + + #-------------------------------------------------------------------------- + # Check that the FFDC name is not a duplicate + #-------------------------------------------------------------------------- + if (exists($ffdcNameToValueHash{$name})) + { + # Two different FFDCs with the same name! + print ("fapiParseErrorInfo.pl ERROR. Duplicate FFDC name ", $name, "\n"); + exit(1); + } + + #-------------------------------------------------------------------------- + # Figure out the FFDC enum-value. This is a hash value generated from + # the FFDC name. + #-------------------------------------------------------------------------- + my $ffdcHash128Bit = md5_hex($name); + my $ffdcHash32Bit = substr($ffdcHash128Bit, 0, 8); + + #-------------------------------------------------------------------------- + # Check that the error enum-value is not a duplicate + #-------------------------------------------------------------------------- + if (exists($ffdcValuePresentHash{$ffdcHash32Bit})) + { + # Two different FFDCs generate the same hash-value! + print ("fapiParseAttributeInfo.pl ERROR. Duplicate FFDC hash value\n"); + exit(1); + } + + #-------------------------------------------------------------------------- + # Update the hashes with the error name and ID + #-------------------------------------------------------------------------- + $ffdcValuePresentHash{$ffdcHash32Bit} = 1; + $ffdcNameToValueHash{$name} = $ffdcHash32Bit; +} + +#------------------------------------------------------------------------------ +# Subroutine to create ffdc methods +#------------------------------------------------------------------------------ +sub addFfdcMethod +{ + my $methods = shift; + my $ffdc_uc = shift; + my $class_name = shift; + my $type = shift; + my $ffdc_lc = lc($ffdc_uc); + + # If we didn't get a type passed in, this element will get an ffdc_t pair. + $type = $ffdc_type if ($type eq undef); + + # Mangle the uppercase name if needed + $ffdc_uc = $mangle_names{$ffdc_uc} if ($mangle_names{$ffdc_uc} ne undef); + + my $key = $ffdc_lc.$type; + my $key_target = $ffdc_lc.$target_ffdc_type; + my $key_ffdc = $ffdc_lc.$ffdc_type; + + # Check to see if this element already has been recorded with this + # type or a target type. Note the effect we're shooting for here is + # to define the member if it's not been defined before *or* it's + # changing from an ffdc_t to a target due to other information in the xml + return if ($methods->{$key}{type} eq $type); + return if ($methods->{$key_target}{type} eq $target_ffdc_type); + + # Just leave if this is a variable_buffer ans we're not supporting that. + return if (($type eq $variable_buffer_ffdc_type) && ($arg_use_variable_buffers eq undef)); + + # Set the proper type, and clear out any previous members/methods if + # we're going from an ffdc_t to a target. + $methods->{$key}{type} = $type; + delete $methods->{$key_ffdc} if ($type eq $target_ffdc_type); + + my $method = ""; + my $method_body = ""; + + if ($type eq $ffdc_type) + { + $method = "\n template< typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr >\n"; + $method .= " $class_name& set_$ffdc_lc(const T& i_value)\n"; + $method_body = " {$ffdc_uc.ptr() = &i_value; $ffdc_uc.size() = fapi2::getErrorInfoFfdcSize(i_value); return *this;}\n\n"; + + $methods->{$key}{member} = "$ffdc_type $ffdc_uc;\n "; + } + + elsif ($type eq $buffer_ffdc_type) + { + # Two methods - one for integral buffers and one for variable_buffers + $method = "\n template< typename T >\n"; + $method .= " $class_name& set_$ffdc_lc(const fapi2::buffer<T>& i_value)\n"; + $method_body = " {$ffdc_uc.ptr() = &i_value(); $ffdc_uc.size() = i_value.template getLength<uint8_t>(); return *this;}\n\n"; + + $methods->{$key}{member} = "$ffdc_type $ffdc_uc;\n "; + } + + elsif ($type eq $variable_buffer_ffdc_type) + { + $method = "\n $class_name& set_$ffdc_lc(const fapi2::variable_buffer& i_value)\n"; + $method_body = " {$ffdc_uc.ptr() = &i_value(); $ffdc_uc.size() = i_value.template getLength<uint8_t>(); return *this;}\n\n"; + + # No need to add the member here, it was added with fapi2::buffer. And we can't have variable + # buffer support with out integral buffer support (can we?) + } + + else + { + $method = "\n $class_name& set_$ffdc_lc(const $type& i_value)\n"; + $method_body .= " {$ffdc_uc = &i_value; return *this;}\n\n"; + + $methods->{$key}{member} = "const $type* $ffdc_uc;\n "; + } + + $method .= ($arg_empty_ffdc eq undef) ? $method_body : " {}\n\n"; + $methods->{$key}{method} = $method; +} + +#------------------------------------------------------------------------------ +# Open output files for writing +#------------------------------------------------------------------------------ +my $rcFile = $arg_output_dir; +$rcFile .= "/"; +$rcFile .= "hwp_return_codes.H"; +open(RCFILE, ">", $rcFile); + +my $eiFile = $arg_output_dir; +$eiFile .= "/"; +$eiFile .= "hwp_error_info.H"; +open(EIFILE, ">", $eiFile); + +my $ecFile = $arg_output_dir; +$ecFile .= "/"; +$ecFile .= "hwp_ffdc_classes.H"; +open(ECFILE, ">", $ecFile); + +my $crFile = $arg_output_dir; +$crFile .= "/"; +$crFile .= "collect_reg_ffdc.C"; +open(CRFILE, ">", $crFile); + +my $sbFile = $arg_output_dir; +$sbFile .= "/"; +$sbFile .= "set_sbe_error.H"; +open(SBFILE, ">", $sbFile); + +#------------------------------------------------------------------------------ +# Print start of file information to hwp_error_info.H +#------------------------------------------------------------------------------ +print EIFILE "// hwp_error_info.H\n"; +print EIFILE "// This file is generated by the perl script parseErrorInfo.pl\n\n"; +print EIFILE "#ifndef FAPI2_HWPERRORINFO_H_\n"; +print EIFILE "#define FAPI2_HWPERRORINFO_H_\n\n"; +print EIFILE "#include <target.H>\n"; +print EIFILE "#include <return_code.H>\n"; +print EIFILE "#include <plat_trace.H>\n"; +print EIFILE "/**\n"; +print EIFILE " * \@brief Error Information macros and HwpFfdcId enumeration\n"; +print EIFILE " *\/\n"; + +#------------------------------------------------------------------------------ +# Print start of file information to hwp_ffdc_classes.H +#------------------------------------------------------------------------------ +print ECFILE "// hwp_ffdc_classes.H\n"; +print ECFILE "// This file is generated by the perl script parseErrorInfo.pl\n\n"; +print ECFILE "#ifndef FAPI2_HWP_FFDC_CLASSES_H_\n"; +print ECFILE "#define FAPI2_HWP_FFDC_CLASSES_H_\n\n"; +print ECFILE "#include <ffdc.H>\n"; +print ECFILE "#include <buffer.H>\n"; +print ECFILE "#include <variable_buffer.H>\n" if ($arg_use_variable_buffers ne undef); +print ECFILE "#include <error_info.H>\n"; +print ECFILE "#include <utils.H>\n"; +print ECFILE "#include <hwp_error_info.H>\n"; +print ECFILE "#include <collect_reg_ffdc.H>\n"; +#print ECFILE "#include <proc_extract_sbe_rc.H>\n\n"; +print ECFILE "/**\n"; +print ECFILE " * \@brief FFDC gathering classes\n"; +print ECFILE " *\/\n"; +print ECFILE "namespace fapi2\n{\n"; + +#------------------------------------------------------------------------------ +# Print start of file information to collectRegFfdc.C +#------------------------------------------------------------------------------ +print CRFILE "// collect_reg_ffdc.C\n"; +print CRFILE "// This file is generated by the perl script parseErrorInfo.pl\n\n"; +print CRFILE "#include <stdint.h>\n"; +print CRFILE "#include <vector>\n"; + +print CRFILE "#include <buffer.H>\n"; +print CRFILE "#include <collect_reg_ffdc.H>\n"; +print CRFILE "#include <target.H>\n"; +print CRFILE "#include <return_code.H>\n"; +print CRFILE "#include <hw_access.H>\n"; +print CRFILE "#include <plat_trace.H>\n\n"; + +print CRFILE "namespace fapi2\n"; +print CRFILE "{\n"; +print CRFILE "void collectRegFfdc(const fapi2::Target<TARGET_TYPE_ALL>* i_target,\n"; +print CRFILE " const fapi2::HwpFfdcId i_ffdcId,\n"; +print CRFILE " fapi2::ReturnCode & o_rc,\n"; +print CRFILE " const TargetType i_child,\n"; +print CRFILE " const TargetType i_presChild,\n"; +print CRFILE " uint32_t i_childOffsetMult)\n"; +print CRFILE "{\n"; +print CRFILE " FAPI_INF(\"collectRegFfdc. FFDC ID: 0x%x\", i_ffdcId);\n"; +print CRFILE " fapi2::ReturnCode l_rc;\n"; +print CRFILE " fapi2::buffer<uint64_t> l_buf;\n"; +print CRFILE " uint32_t l_cfamData = 0;\n"; +print CRFILE " uint64_t l_scomData = 0;\n"; +print CRFILE " std::vector<uint32_t> l_cfamAddresses;\n"; +print CRFILE " std::vector<uint64_t> l_scomAddresses;\n"; +print CRFILE " uint32_t l_ffdcSize = 0;\n\n"; +print CRFILE " switch (i_ffdcId)\n"; +print CRFILE " {\n"; + +#------------------------------------------------------------------------------ +# Print start of file information to setSbeError.H +#------------------------------------------------------------------------------ +print SBFILE "// setSbeError.H\n"; +print SBFILE "// This file is generated by the perl script parseErrorInfo.pl\n\n"; +print SBFILE "// When SBE code creates an error, it produces an error value\n"; +print SBFILE "// that matches a value in the HwpReturnCode enum in\n"; +print SBFILE "// fapiHwpReturnCodes.H. The SBE uses the __ASSEMBLER__\n"; +print SBFILE "// primitives in hwpReturnCodes.H to do this. The function\n"; +print SBFILE "// that extracts the error value from the SBE needs to call\n"; +print SBFILE "// FAPI_SET_HWP_ERROR to create the error and get all the\n"; +print SBFILE "// actions in the error XML file performed, but that macro can\n"; +print SBFILE "// only be called with the enumerator, not the value. This\n"; +print SBFILE "// FAPI_SET_SBE_ERROR macro can be called instead, it calls\n"; +print SBFILE "// FAPI_SET_HWP_ERROR with the correct error enumerator.\n"; +print SBFILE "// Errors containing <sbeError/> in their XML are supported\n"; +print SBFILE "// in this macro.\n\n"; +print SBFILE "// Note that it is expected that this macro will be called\n"; +print SBFILE "// in one place (the function that extracts the error from\n"; +print SBFILE "// the SBE), if this changes and it is called in multiple\n"; +print SBFILE "// places then the macro could be turned into a function to\n"; +print SBFILE "// avoid the code size increase of expanding the macro in\n"; +print SBFILE "// multiple places. The function approach is slightly more\n"; +print SBFILE "// complicated, there is an extra C file and the function\n"; +print SBFILE "// must take a parameter for the generic chip ID in the error\n"; +print SBFILE "// XML.\n\n"; +print SBFILE "#ifndef FAPI2_SETSBEERROR_H_\n"; +print SBFILE "#define FAPI2_SETSBEERROR_H_\n\n"; +print SBFILE "#define FAPI_SET_SBE_ERROR(RC, ERRVAL)\\\n"; +print SBFILE "{\\\n"; +print SBFILE "switch (ERRVAL)\\\n"; +print SBFILE "{\\\n"; + +#------------------------------------------------------------------------------ +# For each XML file +#------------------------------------------------------------------------------ +foreach my $argnum (0 .. $#ARGV) +{ + my $infile = $ARGV[$argnum]; + my $count = 0; + + #-------------------------------------------------------------------------- + # Read XML file. The ForceArray option ensures that there is an array of + # elements even if there is only one element + #-------------------------------------------------------------------------- + my $errors = $xml->XMLin($infile, ForceArray => + ['hwpError', 'collectFfdc', 'ffdc', 'callout', 'deconfigure', 'gard', + 'registerFfdc', 'collectRegisterFfdc', 'cfamRegister', 'scomRegister', + 'id','collectTrace', 'buffer']); + + # Uncomment to get debug output of all errors + #print "\nFile: ", $infile, "\n", Dumper($errors), "\n"; + + #-------------------------------------------------------------------------- + # For each Error + #-------------------------------------------------------------------------- + foreach my $err (@{$errors->{hwpError}}) + { + # Hash of methods for the ffdc-gathering class + my %methods; + + #---------------------------------------------------------------------- + # Check that expected fields are present + #---------------------------------------------------------------------- + if (! exists $err->{rc}) + { + print ("parseErrorInfo.pl ERROR. rc missing\n"); + exit(1); + } + + if (! exists $err->{description}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. description missing\n"); + exit(1); + } + + #---------------------------------------------------------------------- + # Check that this rc hasn't been deprecated + #---------------------------------------------------------------------- + if ($deprecated{$err->{rc}} ne undef) + { + print "WARNING: $err->{rc} has been deprecated because $deprecated{$err->{rc}}\n"; + next; + } + + #---------------------------------------------------------------------- + # Set the error enum value in a global hash + #--------------------------------------------------------------------- + setErrorEnumValue($err->{rc}); + + #---------------------------------------------------------------------- + # If this is an SBE error, add it to set_sbe_error.H + #---------------------------------------------------------------------- + if (exists $err->{sbeError}) + { + print SBFILE " case fapi2::$err->{rc}:\\\n"; + print SBFILE " FAPI_SET_HWP_ERROR(RC, $err->{rc});\\\n"; + print SBFILE " break;\\\n"; + } + + #---------------------------------------------------------------------- + # Print the CALL_FUNCS_TO_COLLECT_FFDC macro to hwp_error_info.H + #---------------------------------------------------------------------- + print EIFILE "#define $err->{rc}_CALL_FUNCS_TO_COLLECT_FFDC(RC) "; + + # For now, this code is removed. It appears to work just fine but + # will require more of the fapi2 infrastructure to be in place. + # Because the ffdc collection classes create members with real types, + # the declarations of the types need to be visible - and they're not + # right now. When we get further along, we can enable this code. +=begin NO_FFDC_COLLECT_HWP + $count = 0; + + foreach my $collectFfdc (@{$err->{collectFfdc}}) + { + if ($count == 0) + { + print EIFILE "{ fapi2::ReturnCode l_tempRc; "; + } + $count++; + + print EIFILE "FAPI_EXEC_HWP(l_tempRc, $collectFfdc, RC); "; + + # collectFfdc is a string we're going to stuff into FAPI_EXEC_HWP + # but we need to create the arguments in the ffdc class. The first + # element inthe collectFfdc string is the function to call. + my @elements = split /,/, $collectFfdc; + my @signature = @{$signatures{@elements[0]}}; + for (my $i = 1; $i <= $#elements; $i++) + { + @elements[$i] =~ s/^\s+|\s+$//g; + addFfdcMethod(\%methods, @elements[$i], lc($err->{rc}), @signature[$i-1]); + } + } + + if ($count > 0) + { + print EIFILE "}"; + } +=cut NO_FFDC_COLLECT_HWP + print EIFILE "\n"; + + #---------------------------------------------------------------------- + # Print the CALL_FUNCS_TO_COLLECT_REG_FFDC macro to hwp_error_info.H + #---------------------------------------------------------------------- + print EIFILE "#define $err->{rc}_CALL_FUNCS_TO_COLLECT_REG_FFDC(RC) "; + + foreach my $collectRegisterFfdc (@{$err->{collectRegisterFfdc}}) + { + #------------------------------------------------------------------ + # Check that expected fields are present + #------------------------------------------------------------------ + if (! exists $collectRegisterFfdc->{id}[0]) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. id(s) missing from collectRegisterFfdc\n"); + exit(1); + } + foreach my $id (@{$collectRegisterFfdc->{id}}) + { + #--------------------------------------------------------------------------------- + # Check FFDC register collection type: target, child, or based on present children + #--------------------------------------------------------------------------------- + if (exists $collectRegisterFfdc->{target}) + { + print EIFILE "fapi2::collectRegFfdc($collectRegisterFfdc->{target}, "; + print EIFILE "fapi2::$id, RC, fapi2::TARGET_TYPE_NONE, fapi2::TARGET_TYPE_NONE); "; + addFfdcMethod(\%methods, $collectRegisterFfdc->{target}, + lc($err->{rc}), $target_ffdc_type); + } + elsif (exists $collectRegisterFfdc->{childTargets}) + { + if (! exists $collectRegisterFfdc->{childTargets}->{parent}) + { + print ("parseErrorInfo.pl ERROR: parent missing from collectRegisterFfdc\n"); + exit(1); + } + if (! exists $collectRegisterFfdc->{childTargets}->{childType}) + { + print ("parseErrorInfo.pl ERROR: childType missing from collectRegisterFfdc\n"); + exit(1); + } + print EIFILE "fapi2::collectRegFfdc($collectRegisterFfdc->{childTargets}->{parent}, fapi2::$id, "; + print EIFILE "RC, fapi2::$collectRegisterFfdc->{childTargets}->{childType}, fapi2::TARGET_TYPE_NONE); "; + addFfdcMethod(\%methods, $collectRegisterFfdc->{childTargets}->{parent}, + lc($err->{rc}), $target_ffdc_type); + } + elsif (exists $collectRegisterFfdc->{basedOnPresentChildren}) + { + if (! exists $collectRegisterFfdc->{basedOnPresentChildren}->{target}) + { + print ("parseErrorInfo.pl ERROR: target missing from collectRegisterFfdc\n"); + exit(1); + } + if (! exists $collectRegisterFfdc->{basedOnPresentChildren}->{childType}) + { + print ("parseErrorInfo.pl ERROR: childType missing from collectRegisterFfdc\n"); + exit(1); + } + if (! exists $collectRegisterFfdc->{basedOnPresentChildren}->{childPosOffsetMultiplier}) + { + print ("parseErrorInfo.pl ERROR: childPosOffsetMultiplier missing from collectRegisterFfdc\n"); + exit(1); + } + print EIFILE "fapi2::collectRegFfdc($collectRegisterFfdc->{basedOnPresentChildren}->{target}, fapi2::$id, RC, "; + print EIFILE "fapi2::TARGET_TYPE_NONE, fapi2::$collectRegisterFfdc->{basedOnPresentChildren}->{childType}, "; + print EIFILE "$collectRegisterFfdc->{basedOnPresentChildren}->{childPosOffsetMultiplier}); "; + addFfdcMethod(\%methods, $collectRegisterFfdc->{basedOnPresentChildren}->{target}, + lc($err->{rc}), $target_ffdc_type); + } + else + { + print ("parseErrorInfo.pl ERROR: Invalid collectRegisterFfdc configuration\n"); + exit(1); + } + } + } + + print EIFILE "\n"; + + #---------------------------------------------------------------------- + # Print the ADD_ERROR_INFO macro to hwp_error_info.H + #---------------------------------------------------------------------- + print EIFILE "#define $err->{rc}_ADD_ERROR_INFO(RC) "; + + # Array of EI Objects + my @eiObjects; + + my $eiObjectStr = "const void * l_objects[] = {"; + my $eiEntryStr = ""; + my $eiEntryCount = 0; + my %cdgTargetHash; # Records the callout/deconfigure/gards for Targets + my %cdgChildHash; # Records the callout/deconfigure/gards for Children + + # collect firmware trace + foreach my $collectTrace (@{$err->{collectTrace}}) + { + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_COLLECT_TRACE; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].collect_trace.iv_eieTraceId = fapi2::CollectTraces::$collectTrace; \\\n"; + $eiEntryCount++; + } + + # Local FFDC + foreach my $ffdc (@{$err->{ffdc}}) + { + # Set the FFDC ID value in a global hash. The name is <rc>_<ffdc> + my $ffdcName = $err->{rc} . "_"; + $ffdcName = $ffdcName . $ffdc; + setFfdcIdValue($ffdcName); + + # Add the FFDC data to the EI Object array if it doesn't already exist + my $objNum = addEntryToArray(\@eiObjects, $ffdc); + + # Add a method to the ffdc-gathering class + addFfdcMethod(\%methods, $ffdc, lc($err->{rc})); + + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_FFDC; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcObjIndex = $objNum; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcId = fapi2::$ffdcName; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcSize = fapi2::getErrorInfoFfdcSize($ffdc); \\\n"; + $eiEntryCount++; + } + + # Buffers, looks a lot like local ffdc + foreach my $buffer (@{$err->{buffer}}) + { + # Set the FFDC ID value in a global hash. The name is <rc>_<ffdc> + my $bufferName = $err->{rc} . "_"; + $bufferName = $bufferName . $buffer; + setFfdcIdValue($bufferName); + + # Add the FFDC data to the EI Object array if it doesn't already exist + my $objNum = addEntryToArray(\@eiObjects, $buffer); + + # Add a method to the ffdc-gathering class - one for each buffer type + addFfdcMethod(\%methods, $buffer, lc($err->{rc}), $buffer_ffdc_type); + addFfdcMethod(\%methods, $buffer, lc($err->{rc}), $variable_buffer_ffdc_type); + + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_FFDC; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcObjIndex = $objNum; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcId = fapi2::$bufferName; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcSize = fapi2::getErrorInfoFfdcSize($buffer); \\\n"; + $eiEntryCount++; + } + + # Procedure/Target/Bus/Child callouts + foreach my $callout (@{$err->{callout}}) + { + if (! exists $callout->{priority}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Callout priority missing\n"); + exit(1); + } + + my $elementsFound = 0; + if (exists $callout->{hw}) + { + # HW Callout + if (! exists $callout->{hw}->{hwid}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. HW Callout hwid missing\n"); + exit(1); + } + + # Check that those HW callouts that need reference targets have them + if (($callout->{hw}->{hwid} eq "TOD_CLOCK") || + ($callout->{hw}->{hwid} eq "MEM_REF_CLOCK") || + ($callout->{hw}->{hwid} eq "PROC_REF_CLOCK") || + ($callout->{hw}->{hwid} eq "PCI_REF_CLOCK")) + { + if (! exists $callout->{hw}->{refTarget}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Callout missing refTarget\n"); + exit(1); + } + } + + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_HW_CALLOUT; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].hw_callout.iv_hw = fapi2::HwCallouts::$callout->{hw}->{hwid}; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].hw_callout.iv_calloutPriority = fapi2::CalloutPriorities::$callout->{priority}; \\\n"; + if (exists $callout->{hw}->{refTarget}) + { + # Add the Targets to the objectlist if they don't already exist + my $objNum = addEntryToArray(\@eiObjects, $callout->{hw}->{refTarget}); + $eiEntryStr .= " l_entries[$eiEntryCount].hw_callout.iv_refObjIndex = $objNum; \\\n"; + + # Add a method to the ffdc-gathering class + addFfdcMethod(\%methods, $callout->{hw}->{refTarget}, lc($err->{rc})); + } + else + { + $eiEntryStr .= " l_entries[$eiEntryCount].hw_callout.iv_refObjIndex = 0xff; \\\n"; + } + $eiEntryCount++; + $elementsFound++; + } + if (exists $callout->{procedure}) + { + # Procedure Callout + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_PROCEDURE_CALLOUT; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].proc_callout.iv_procedure = fapi2::ProcedureCallouts::$callout->{procedure}; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].proc_callout.iv_calloutPriority = fapi2::CalloutPriorities::$callout->{priority}; \\\n"; + $eiEntryCount++; + $elementsFound++; + } + if (exists $callout->{bus}) + { + # A Bus Callout consists of two targets separated by + # commas/spaces + my @targets = split(/\s*,\s*|\s+/, $callout->{bus}); + + if (scalar @targets != 2) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. did not find two targets in bus callout\n"); + exit(1); + } + + # Check the type of the Targets + print EIFILE "fapi2::checkType<const $target_ffdc_type *>($targets[0]); \\\n"; + print EIFILE "fapi2::checkType<const $target_ffdc_type *>($targets[1]); \\\n"; + + # Add the Targets to the objectlist if they don't already exist + my $objNum1 = addEntryToArray(\@eiObjects, $targets[0]); + + my $objNum2 = addEntryToArray(\@eiObjects, $targets[1]); + + # Add a method to the ffdc-gathering class + addFfdcMethod(\%methods, $targets[0], lc($err->{rc}), $target_ffdc_type); + addFfdcMethod(\%methods, $targets[1], lc($err->{rc}), $target_ffdc_type); + + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_BUS_CALLOUT; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].bus_callout.iv_endpoint1ObjIndex = $objNum1; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].bus_callout.iv_endpoint2ObjIndex = $objNum2; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].bus_callout.iv_calloutPriority = fapi2::CalloutPriorities::$callout->{priority}; \\\n"; + $eiEntryCount++; + $elementsFound++; + } + if (exists $callout->{target}) + { + # Add the Target to cdgTargetHash to be processed with any + # deconfigure and GARD requests + $cdgTargetHash{$callout->{target}}{callout} = 1; + $cdgTargetHash{$callout->{target}}{priority} = + $callout->{priority}; + + $elementsFound++; + } + if (exists $callout->{childTargets}) + { + # Check that the parent and childType subelements exist + if (! exists $callout->{childTargets}->{parent}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child Callout parent missing\n"); + exit(1); + } + + if (! exists $callout->{childTargets}->{childType}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child Callout childType missing\n"); + exit(1); + } + + # Add the child info to cdgChildHash to be processed with + # any deconfigure and GARD requests + my $parent = $callout->{childTargets}->{parent}; + my $childType = $callout->{childTargets}->{childType}; + $cdgChildHash{$parent}{$childType}{callout} = 1; + $cdgChildHash{$parent}{$childType}{priority} = + $callout->{priority}; + + $elementsFound++; + + if (exists $callout->{childTargets}->{childPort}) + { + my $childPort = $callout->{childTargets}->{childPort}; + + $cdgChildHash{$parent}{$childType}{childPort} = $childPort; + } + + if (exists $callout->{childTargets}->{childNumber}) + { + my $childNum = $callout->{childTargets}->{childNumber}; + $cdgChildHash{$parent}{$childType}{childNumber} = $childNum; + } + + } + if ($elementsFound == 0) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Callout incomplete\n"); + exit(1); + } + elsif ($elementsFound > 1) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Callout has multiple elements\n"); + exit(1); + } + } # callout + + # Target/Child deconfigures + foreach my $deconfigure (@{$err->{deconfigure}}) + { + my $elementsFound = 0; + if (exists $deconfigure->{target}) + { + # Add the Target to cdgTargetHash to be processed with any + # callout and GARD requests + $cdgTargetHash{$deconfigure->{target}}{deconf} = 1; + $elementsFound++; + } + if (exists $deconfigure->{childTargets}) + { + # Check that the parent and childType subelements exist + if (! exists $deconfigure->{childTargets}->{parent}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child Deconfigure parent missing\n"); + exit(1); + } + if (! exists $deconfigure->{childTargets}->{childType}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child Deconfigure childType missing\n"); + exit(1); + } + + # Add the child info to cdgChildHash to be processed with + # any callout and GARD requests + my $parent = $deconfigure->{childTargets}->{parent}; + my $childType = $deconfigure->{childTargets}->{childType}; + $cdgChildHash{$parent}{$childType}{deconf} = 1; + + $elementsFound++; + + if ( exists $deconfigure->{childTargets}->{childPort}) + { + my $childPort = $deconfigure->{childTargets}->{childPort}; + + $cdgChildHash{$parent}{$childType}{childPort} = $childPort; + } + + if ( exists $deconfigure->{childTargets}->{childNumber}) + { + my $childNum = $deconfigure->{childTargets}->{childNumber}; + $cdgChildHash{$parent}{$childType}{childNumber} = $childNum; + + } + } + if ($elementsFound == 0) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Deconfigure incomplete\n"); + exit(1); + } + elsif ($elementsFound > 1) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Deconfigure has multiple elements\n"); + exit(1); + } + } # deconfigure + + # Target/Child Gards + foreach my $gard (@{$err->{gard}}) + { + my $elementsFound = 0; + if (exists $gard->{target}) + { + # Add the Target to cdgTargetHash to be processed with any + # callout and deconfigure requests + $cdgTargetHash{$gard->{target}}{gard} = 1; + $elementsFound++; + } + if (exists $gard->{childTargets}) + { + # Check that the parent and childType subelements exist + if (! exists $gard->{childTargets}->{parent}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child GARD parent missing\n"); + exit(1); + } + if (! exists $gard->{childTargets}->{childType}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child GARD childType missing\n"); + exit(1); + } + + # Add the child info to cdgChildHash to be processed with + # any callout and deconfigure requests + my $parent = $gard->{childTargets}->{parent}; + my $childType = $gard->{childTargets}->{childType}; + $cdgChildHash{$parent}{$childType}{gard} = 1; + + $elementsFound++; + + if ( exists $gard->{childTargets}->{childPort}) + { + my $childPort = $gard->{childTargets}->{childPort}; + + $cdgChildHash{$parent}{$childType}{childPort} = $childPort; + + } + + if ( exists $gard->{childTargets}->{childNumber}) + { + my $childNum = $gard->{childTargets}->{childNumber}; + $cdgChildHash{$parent}{$childType}{childNumber} = $childNum; + } + } + if ($elementsFound == 0) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. GARD incomplete\n"); + exit(1); + } + elsif ($elementsFound > 1) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. GARD has multiple elements\n"); + exit(1); + } + } # gard + + # Process the callout, deconfigures and GARDs for each Target + foreach my $cdg (keys %cdgTargetHash) + { + # Check the type + print EIFILE "fapi2::checkType<const $target_ffdc_type *>($cdg); \\\n"; + + my $callout = 0; + my $priority = 'LOW'; + my $deconf = 0; + my $gard = 0; + + if (exists $cdgTargetHash{$cdg}->{callout}) + { + $callout = 1; + } + if (exists $cdgTargetHash{$cdg}->{priority}) + { + $priority = $cdgTargetHash{$cdg}->{priority}; + } + if (exists $cdgTargetHash{$cdg}->{deconf}) + { + $deconf = 1; + } + if (exists $cdgTargetHash{$cdg}->{gard}) + { + $gard = 1; + } + + # Add the Target to the objectlist if it doesn't already exist + my $objNum = addEntryToArray(\@eiObjects, $cdg); + + # Add a method to the ffdc-gathering class + addFfdcMethod(\%methods, $cdg, lc($err->{rc}), $target_ffdc_type); + + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_CDG; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].target_cdg.iv_targetObjIndex = $objNum; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].target_cdg.iv_callout = $callout; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].target_cdg.iv_deconfigure = $deconf; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].target_cdg.iv_gard = $gard; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].target_cdg.iv_calloutPriority = fapi2::CalloutPriorities::$priority; \\\n"; + $eiEntryCount++; + } + + # Process the callout, deconfigures and GARDs for Child Targets + foreach my $parent (keys %cdgChildHash) + { + # Check the type + print EIFILE "fapi2::checkType<const $target_ffdc_type *>($parent); \\\n"; + + foreach my $childType (keys %{$cdgChildHash{$parent}}) + { + my $callout = 0; + my $priority = 'LOW'; + my $deconf = 0; + my $gard = 0; + my $childPort = 0xFF; + my $childNumber = 0xFF; + + if (exists $cdgChildHash{$parent}{$childType}->{callout}) + { + $callout = 1; + } + if (exists $cdgChildHash{$parent}->{$childType}->{priority}) + { + $priority = + $cdgChildHash{$parent}->{$childType}->{priority}; + } + if (exists $cdgChildHash{$parent}->{$childType}->{deconf}) + { + $deconf = 1; + } + if (exists $cdgChildHash{$parent}->{$childType}->{childPort}) + { + $childPort = + $cdgChildHash{$parent}->{$childType}->{childPort} ; + addFfdcMethod(\%methods, $childPort, lc($err->{rc})); + } + if (exists $cdgChildHash{$parent}->{$childType}->{childNumber}) + { + $childNumber = + $cdgChildHash{$parent}->{$childType}->{childNumber} ; + addFfdcMethod(\%methods, $childNumber, lc($err->{rc})); + } + if (exists $cdgChildHash{$parent}->{$childType}->{gard}) + { + $gard = 1; + } + + + # Add the Target to the objectlist if it doesn't already exist + my $objNum = addEntryToArray(\@eiObjects, $parent); + addFfdcMethod(\%methods, $parent, lc($err->{rc}), $target_ffdc_type); + + # Add an EI entry to eiEntryStr + $eiEntryStr .= + " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_CHILDREN_CDG; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_parentObjIndex = $objNum; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_callout = $callout; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_deconfigure = $deconf; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_childType = fapi2::$childType; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_childPort = $childPort; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_childNumber = $childNumber; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_gard = $gard; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_calloutPriority = fapi2::CalloutPriorities::$priority; \\\n"; + $eiEntryCount++; + } + } + + # Add all objects to $eiObjectStr + my $objCount = 0; + + foreach my $eiObject (@eiObjects) + { + if ($objCount > 0) + { + $eiObjectStr .= ", "; + } + + if ($mangle_names{$eiObject} eq undef) + { + $eiObjectStr .= "$eiObject" + } + else + { + $eiObjectStr .= $mangle_names{$eiObject}; + } + + $objCount++; + } + $eiObjectStr .= "};"; + + # Print info to file + if ($eiEntryCount > 0) + { + print EIFILE "\\\n{ \\\n $eiObjectStr \\\n"; + print EIFILE " fapi2::ErrorInfoEntry l_entries[$eiEntryCount]; \\\n"; + print EIFILE "$eiEntryStr"; + print EIFILE " RC.addErrorInfo(l_objects, l_entries, $eiEntryCount); \\\n}"; + } + + print EIFILE "\n"; + + #---------------------------------------------------------------------- + # Print the return code class to hwp_error_info.H + #---------------------------------------------------------------------- + # Remove the repeated whitespace and newlines other characters from the description + $err->{description} =~ s/^\s+|\s+$|"//g; + $err->{description} =~ tr{\n}{ }; + $err->{description} =~ s/\h+/ /g; + + #---------------------------------------------------------------------- + # Print the return code class to hwp_error_info.H + #---------------------------------------------------------------------- + my $class_name = lc($err->{rc}); + + # Class declaration + print ECFILE "\nclass $class_name\n{\n public:\n"; + + # Constructor. This traces the description. If this is too much, we can + # remove it. + if ($arg_empty_ffdc eq undef) + { + print ECFILE " $class_name(fapi2::errlSeverity_t i_sev = fapi2::FAPI2_ERRL_SEV_UNRECOVERABLE, fapi2::ReturnCode& i_rc = fapi2::current_err):\n"; + print ECFILE " iv_rc(i_rc),\n"; + print ECFILE " iv_sev(i_sev)\n"; + print ECFILE " { FAPI_ERR(\"$err->{description}\"); }\n"; + } + else + { + print ECFILE " $class_name(fapi2::errlSeverity_t i_sev = fapi2::FAPI2_ERRL_SEV_UNRECOVERABLE, fapi2::ReturnCode& i_rc = fapi2::current_err)\n"; + print ECFILE " {}\n"; + } + + # Methods + foreach my $key (keys %methods) + { + print ECFILE $methods{$key}{method}; + } + + # Stick the execute method at the end of the other methods. + print ECFILE " void execute(void)\n"; + print ECFILE " {\n"; + print ECFILE " FAPI_SET_HWP_ERROR(iv_rc, $err->{rc});\n" if ($arg_empty_ffdc eq undef); + print ECFILE " fapi2::logError(iv_rc, iv_sev);\n" if ($arg_empty_ffdc eq undef); + print ECFILE " }\n\n"; + + # Instance variables + if ($arg_empty_ffdc eq undef) + { + print ECFILE " private:\n "; + foreach my $key (keys %methods) + { + print ECFILE $methods{$key}{member}; + } + + print ECFILE "fapi2::ReturnCode& iv_rc;\n"; + print ECFILE " fapi2::errlSeverity_t iv_sev;\n"; + } + + print ECFILE "};\n\n\n\n"; + } + + #-------------------------------------------------------------------------- + # For each registerFfdc. + #-------------------------------------------------------------------------- + foreach my $registerFfdc (@{$errors->{registerFfdc}}) + { + #---------------------------------------------------------------------- + # Check that expected fields are present + #---------------------------------------------------------------------- + if (! exists $registerFfdc->{id}[0]) + { + print ("parseErrorInfo.pl ERROR. id missing from registerFfdc\n"); + exit(1); + } + + if (scalar @{$registerFfdc->{id}} > 1) + { + print ("parseErrorInfo.pl ERROR. multiple ids in registerFfdc\n"); + exit(1); + } + + #---------------------------------------------------------------------- + # Set the FFDC ID value in a global hash + #---------------------------------------------------------------------- + setFfdcIdValue($registerFfdc->{id}[0]); + + #---------------------------------------------------------------------- + # Generate code to capture the registers in collect_reg_ffdc.C + #---------------------------------------------------------------------- + print CRFILE " case $registerFfdc->{id}[0]:\n"; + +=begin NEED_P9_REGISTERS + # Look for CFAM Register addresses + foreach my $cfamRegister (@{$registerFfdc->{cfamRegister}}) + { + print CRFILE " l_cfamAddresses.push_back($cfamRegister);\n"; + print CRFILE " l_ffdcSize += sizeof(l_cfamData);\n"; + } + + # Look for SCOM Register addresses + foreach my $scomRegister (@{$registerFfdc->{scomRegister}}) + { + print CRFILE " l_scomAddresses.push_back($scomRegister);\n"; + print CRFILE " l_ffdcSize += sizeof(l_scomData);\n"; + } +=cut NEED_P9_REGISTERS + + print CRFILE " break;\n"; + } + +} + +#------------------------------------------------------------------------------ +# Print end of file information to collect_reg_ffdc.C +#------------------------------------------------------------------------------ +print CRFILE " default:\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: Invalid FFDC ID 0x%x\", "; +print CRFILE "i_ffdcId);\n"; +print CRFILE " return;\n"; +print CRFILE " }\n\n"; + +=begin NEED_P9_REGISTERS + +print CRFILE " uint8_t * l_pBuf = NULL;\n"; +print CRFILE " uint8_t * l_pData = NULL;\n"; +print CRFILE " std::vector<fapi::Target> l_targets;\n"; +print CRFILE " uint32_t l_chipletPos32 = 0;\n"; +#--------------------------------------------------------------------------------------------------------- +# Populate chiplet vectors (if required by register collection method) and adjust buffer sizes accordingly +#--------------------------------------------------------------------------------------------------------- +print CRFILE " if (fapi2::TARGET_TYPE_NONE != i_child)\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetChildChiplets(i_target, i_child, l_targets, TARGET_STATE_FUNCTIONAL);\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: Error: fapiGetChildChiplets: failed to get chiplets.\");\n"; +print CRFILE " return;\n"; +print CRFILE " }\n"; +print CRFILE " if (l_targets.empty())\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_INF(\"collect_reg_ffdc.C: Error: No functional chiplets found. \");\n"; +print CRFILE " return;\n"; +print CRFILE " }\n"; +print CRFILE " l_ffdcSize += sizeof(l_chipletPos32);\n"; +print CRFILE " l_ffdcSize *= l_targets.size();\n"; +print CRFILE " l_pBuf = new uint8_t[l_ffdcSize];\n"; +print CRFILE " l_pData = l_pBuf;\n"; +print CRFILE " }\n"; +print CRFILE " else if (fapi2::TARGET_TYPE_NONE != i_presChild)\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetChildChiplets(i_target, i_presChild, l_targets, TARGET_STATE_PRESENT);\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: Error: fapiGetChildChiplets: failed to get chiplets.\");\n"; +print CRFILE " return;\n"; +print CRFILE " }\n"; +print CRFILE " if (l_targets.empty())\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_INF(\"collect_reg_ffdc.C: Error: No functional chiplets found. \");\n"; +print CRFILE " return;\n"; +print CRFILE " }\n"; +print CRFILE " l_ffdcSize += sizeof(l_chipletPos32);\n"; +print CRFILE " l_ffdcSize *= l_targets.size();\n"; +print CRFILE " l_pBuf = new uint8_t[l_ffdcSize];\n"; +print CRFILE " l_pData = l_pBuf;\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_ffdcSize += sizeof(l_chipletPos32);\n"; +print CRFILE " l_pBuf = new uint8_t[l_ffdcSize];\n"; +print CRFILE " l_pData = l_pBuf;\n"; +print CRFILE " l_targets.push_back(i_target);\n"; +print CRFILE " }\n\n"; +#--------------------------------------------------------------------------------------------------------- +# Obtain target position and insert as the first word in the buffer +#--------------------------------------------------------------------------------------------------------- +print CRFILE " bool l_targIsChiplet = i_target.isChiplet();\n\n"; +print CRFILE " for (std::vector<fapi::Target>::const_iterator targetIter = l_targets.begin();\n"; +print CRFILE " targetIter != l_targets.end(); ++targetIter)\n"; +print CRFILE " {\n"; +print CRFILE " if ((fapi2::TARGET_TYPE_NONE != i_child) ||\n"; +print CRFILE " (fapi2::TARGET_TYPE_NONE != i_presChild) ||\n"; +print CRFILE " (true == l_targIsChiplet))\n"; +print CRFILE " {\n"; +print CRFILE " uint8_t l_chipletPos = 0;\n"; +print CRFILE " l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &(*targetIter), l_chipletPos);\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: Error getting chiplet position\");\n"; +print CRFILE " l_chipletPos = 0xFF;\n"; +print CRFILE " }\n"; + #------------------------------------------------------------------------- + # We print the target's position in the error log whether the target is a + # chip or chiplet, so we need to store the chiplet position in a uint32_t + # to have consitency in the buffer as ATTR_POS below returns a uint32_t + #------------------------------------------------------------------------- +print CRFILE " l_chipletPos32 = l_chipletPos;\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = FAPI_ATTR_GET(ATTR_POS, &(*targetIter), l_chipletPos32);\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: Error getting chip position\");\n"; +print CRFILE " l_chipletPos32 = 0xFFFFFFFF;\n"; +print CRFILE " }\n"; +print CRFILE " }\n"; +print CRFILE " *(reinterpret_cast<uint32_t *>(l_pData)) = l_chipletPos32;\n"; +print CRFILE " l_pData += sizeof(l_chipletPos32);\n"; +#--------------------------------------------------------------------------------------------------------- +# Instert cfam data (if any) related to this chip / chiplet into the buffer +# If collecting FFDC based on present children, adjust the register address by the appropriate offset +#--------------------------------------------------------------------------------------------------------- +print CRFILE " for (std::vector<uint32_t>::const_iterator cfamIter = l_cfamAddresses.begin();\n"; +print CRFILE " cfamIter != l_cfamAddresses.end(); ++cfamIter)\n"; +print CRFILE " {\n"; +print CRFILE " if (fapi2::TARGET_TYPE_NONE != i_presChild)\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetCfamRegister(i_target, (*cfamIter + (l_chipletPos32 * i_childOffsetMult)), l_buf);\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetCfamRegister(*targetIter, *cfamIter, l_buf);\n"; +print CRFILE " }\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: CFAM error for 0x%x\","; +print CRFILE "*cfamIter);\n"; +print CRFILE " l_cfamData = 0xbaddbadd;\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_cfamData = l_buf.getWord(0);\n"; +print CRFILE " }\n"; +print CRFILE " *(reinterpret_cast<uint32_t *>(l_pData)) = l_cfamData;\n"; +print CRFILE " l_pData += sizeof(l_cfamData);\n"; +print CRFILE " }\n\n"; +#--------------------------------------------------------------------------------------------------------- +# Instert any scom data (if any) related to this chip / chiplet into the buffer +# If collecting FFDC based on present children, adjust the register address by the appropriate offset +#--------------------------------------------------------------------------------------------------------- +print CRFILE " for (std::vector<uint64_t>::const_iterator scomIter = l_scomAddresses.begin();\n"; +print CRFILE " scomIter != l_scomAddresses.end(); ++scomIter)\n"; +print CRFILE " {\n"; +print CRFILE " if (fapi2::TARGET_TYPE_NONE != i_presChild)\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetScom(i_target, (*scomIter + (l_chipletPos32 * i_childOffsetMult)), l_buf);\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetScom(*targetIter, *scomIter, l_buf);\n"; +print CRFILE " }\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: SCOM error for 0x%llx\","; +print CRFILE "*scomIter);\n"; +print CRFILE " l_scomData = 0xbaddbaddbaddbaddULL;\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_scomData = l_buf.getDoubleWord(0);\n"; +print CRFILE " }\n"; +print CRFILE " *(reinterpret_cast<uint64_t *>(l_pData)) = l_scomData;\n"; +print CRFILE " l_pData += sizeof(l_scomData);\n"; +print CRFILE " }\n"; +print CRFILE " }\n\n"; +print CRFILE " o_rc.addEIFfdc(i_ffdcId, l_pBuf, l_ffdcSize);\n"; +print CRFILE " delete [] l_pBuf;\n"; +=cut NEED_P9_REGISTERS + +print CRFILE "}\n"; +print CRFILE "}\n"; + + +#------------------------------------------------------------------------------ +# Print the fapiHwpReturnCodes.H file +#------------------------------------------------------------------------------ +print RCFILE "// fapiHwpReturnCodes.H\n"; +print RCFILE "// This file is generated by perl script parseErrorInfo.pl\n\n"; +print RCFILE "#ifndef FAPI2_HWPRETURNCODES_H_\n"; +print RCFILE "#define FAPI2_HWPRETURNCODES_H_\n\n"; +print RCFILE "#ifndef __ASSEMBLER__\n"; +print RCFILE "namespace fapi2\n"; +print RCFILE "{\n\n"; +print RCFILE "/**\n"; +print RCFILE " * \@brief Enumeration of HWP return codes\n"; +print RCFILE " *\/\n"; +print RCFILE "enum HwpReturnCode\n"; +print RCFILE "{\n"; +foreach my $key (keys %errNameToValueHash) +{ + print RCFILE " $key = 0x$errNameToValueHash{$key},\n"; +} +print RCFILE "};\n\n"; +print RCFILE "}\n\n"; +print RCFILE "#else\n"; +foreach my $key (keys %errNameToValueHash) +{ + print RCFILE " .set $key, 0x$errNameToValueHash{$key}\n"; +} +print RCFILE "#endif\n"; +print RCFILE "#endif\n"; + +#------------------------------------------------------------------------------ +# Print the HwpFfdcId enumeration to hwp_error_info.H +#------------------------------------------------------------------------------ +print EIFILE "namespace fapi2\n"; +print EIFILE "{\n\n"; +print EIFILE "/**\n"; +print EIFILE " * \@brief Enumeration of FFDC identifiers\n"; +print EIFILE " *\/\n"; +print EIFILE "enum HwpFfdcId\n"; +print EIFILE "{\n"; +foreach my $key (keys %ffdcNameToValueHash) +{ + print EIFILE " $key = 0x$ffdcNameToValueHash{$key},\n"; +} +print EIFILE "};\n\n"; +print EIFILE "}\n\n"; + +#------------------------------------------------------------------------------ +# Print end of file information to hwp_error_info.H +#------------------------------------------------------------------------------ +print EIFILE "\n\n#endif\n"; + +#------------------------------------------------------------------------------ +# Print end of file information to hwp_ffdc_classes.H +#------------------------------------------------------------------------------ +print ECFILE "\n};\n"; # close the namespace +print ECFILE "\n\n#endif\n"; + +#------------------------------------------------------------------------------ +# Print end of file information to set_sbe_error.H +#------------------------------------------------------------------------------ +print SBFILE " default:\\\n"; +print SBFILE " FAPI_SET_HWP_ERROR(RC, RC_SBE_UNKNOWN_ERROR);\\\n"; +print SBFILE " break;\\\n"; +print SBFILE "}\\\n"; +print SBFILE "}\n\n"; +print SBFILE "#endif\n"; + +#------------------------------------------------------------------------------ +# Close output files +#------------------------------------------------------------------------------ +close(RCFILE); +close(EIFILE); +close(ECFILE); +close(CRFILE); +close(SBFILE); diff --git a/src/ppe/hwpf/fapi/xml/buffer_errors.xml b/src/ppe/hwpf/fapi/xml/buffer_errors.xml new file mode 100755 index 0000000..4cf6718 --- /dev/null +++ b/src/ppe/hwpf/fapi/xml/buffer_errors.xml @@ -0,0 +1,40 @@ +<!-- IBM_PROLOG_BEGIN_TAG --> +<!-- This is an automatically generated prolog. --> +<!-- --> +<!-- $Source: src/ppe/hwpf/fapi/xml/buffer_errors.xml $ --> +<!-- --> +<!-- OpenPOWER OnChipController Project --> +<!-- --> +<!-- Contributors Listed Below - COPYRIGHT 2012,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 --> + +<hwpErrors> + + <hwpError> + <rc>RC_FAPI2_BUFFER</rc> + <description> + fapi2 error from a buffer operation + </description> + <buffer>BUFFER</buffer> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + +</hwpErrors> diff --git a/src/ppe/hwpf/plat/.empty b/src/ppe/hwpf/plat/.empty new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/hwpf/plat/.empty diff --git a/src/ppe/hwpf/plat/include/array.H b/src/ppe/hwpf/plat/include/array.H new file mode 100644 index 0000000..ca83088 --- /dev/null +++ b/src/ppe/hwpf/plat/include/array.H @@ -0,0 +1,174 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/array.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file array.H + * @brief definitions for fapi2 arrays + */ + +#ifndef __FAPI2_ARRAY__ +#define __FAPI2_ARRAY__ + +#include <stdint.h> +#include <utility> +#include <assert.h> +#include <string.h> + +namespace fapi2 +{ + /// + /// @brief Class representing a FAPI2 array + /// FAPI2 arrays are defined to be very lightweight but support + /// c++ container operations (iterators, bounds checking, assignment, etc.) + /// To avoid the code-bloat associated with std::vector templates, + /// fapi2::array is presently limited to 64-bit elements. + /// + /// To construct an array, you can either pass in an existing chunk + /// of memory, or let the container allocate memory for you: + /// fapi2::array foo(3, &PIB_MEM_BLOCK); + /// creates an array 3 x uit64_t in size, located at &PIB_MEM_BLOCK. + /// The memory pointed to by the address passed in is untouched + /// during creation. This allows for a light-weight overlay on top + /// of existing memory. It also means you need to initialize the space + /// yourself. + /// fapi2_array foo(3); + /// creates an array 3 x uint64_t in size, and that memory will be + /// allocated by the constructor and initiaized to 0's. + /// + /// + class array + { + public: + + typedef uint64_t element_type; + typedef element_type* iterator; + typedef const element_type* const_iterator; + + /// + /// @brief Create an array + /// @param[in] the size of the array + /// @param[in] a pointer to memory of appropriate size + /// defaults to nullptr which causes the platform to + /// allocate memory of size * element_type + /// @warning fapi2::arrays, like arrays, can not be re-sized after + /// creation. + /// + array(const uint32_t i_size, element_type* i_data = nullptr); + + /// + /// @brief Destroy an array + /// + ~array(void); + + /// + /// @brief operator[] + /// @param[in] the index of the element + /// @return a reference to the element in question. + /// @note array[0] = 0 works as well as foo = array[0] + /// + element_type& operator[](const uint32_t i_index); + + /// + /// @brief operator=() + /// @param[in] the other array + /// @return a reference to this, after the assignement + /// + array& operator=(const array& i_other); + + /// + /// @brief move operator=() + /// @note To use: new_array = std::move(old_array). old_array will be + /// destroyed and no copy will be made (moved) + /// + array& operator=(array&& i_other); + + /// + /// @brief operator==() + /// + bool operator==(const array& i_other); + + /// + /// @brief operator!=() + /// + __attribute__ ((always_inline)) + bool operator!=(const array& i_other) + { return ! operator==(i_other); } + + /// + /// @brief Return an iterator the to beginning of the array + /// @return An iterator to the beginning of the array + /// + __attribute__ ((always_inline)) + iterator begin(void) + { return iv_data; } + + /// + /// @brief Return an iterator the to end of the array + /// @return An iterator to the end of the array + /// + __attribute__ ((always_inline)) + iterator end(void) + { return iv_data + size(); } + + /// + /// @brief Return a const_iterator the to beginning of the array + /// @return A const_iterator to the beginning of the array + /// + __attribute__ ((always_inline)) + const_iterator begin(void) const + { return iv_data; } + + /// + /// @brief Return a const_iterator the to end of the array + /// @return A const_iterator to the end the array + /// + __attribute__ ((always_inline)) + const_iterator end(void) const + { return iv_data + size(); } + + private: + + enum + { + // Bit in iv_size representing whether we delete in the dtor + delete_bit = 0x80000000, + + // The resulting size limit + size_limit = 0x7FFFFFFF, + }; + + __attribute__ ((always_inline)) + uint32_t size(void) + { return (iv_size & ~delete_bit); } + + __attribute__ ((always_inline)) + uint32_t size(void) const + { return (iv_size & ~delete_bit); } + + uint32_t iv_size; + element_type* iv_data; + }; +} + +#endif diff --git a/src/ppe/hwpf/plat/include/buffer.H b/src/ppe/hwpf/plat/include/buffer.H new file mode 100644 index 0000000..607107d --- /dev/null +++ b/src/ppe/hwpf/plat/include/buffer.H @@ -0,0 +1,423 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/buffer.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file buffer.H + * @brief definitions for fapi2 variable integral buffers + */ + +#ifndef __FAPI2_INTEGRAL_BUFFER__ +#define __FAPI2_INTEGRAL_BUFFER__ + +#include <buffer_base.H> +#include <return_code.H> + +namespace fapi2 +{ + /// @brief Class representing a FAPI buffer<T> + /// @note Buffers support method chaining. So, rather than + /// this + /// @code + /// buffer<T> mask; + /// mask.setBit<B>(); + /// mask.invert(); + /// my_buffer &= mask; + /// @endcode + /// You can do + /// @code + /// my_buffer &= buffer<T>().setBit<B>.invert(); + /// @endcode + template <typename T> + class buffer : public buffer_base<T> + { + public: + /// Shortcut typedef to map to our traits class + typedef typename buffer_base<T, buffer>::bits_type bits_type; + + /// + /// @brief Integral buffer assignment constructor + /// @param[in] i_value initial value of the buffer + /// Meaningless for variable types and thus protected. + /// + inline buffer(T i_value = 0) + { + // Why not an initializer list? That would force buffer_base<T> + // to have a ctor which took a T, and I want to avoid that in + // the generic case: this makes it more clear that the two + // ctor's (integral and container) behave very differently. + // variable_buffers also have a ctor which takes a single + // numerical value, and that represents a bit count, not an + // initial value. + this->iv_data = i_value; + } + + + /// @name Bit/Word Manipulation Functions + ///@{ + + /// + /// @brief Return the length of the buffer in bits + /// @return Length in bits + /// + inline constexpr uint32_t getBitLength(void) const + { return bufferTraits<T>::bit_length(this->iv_data); } + + /// + /// @brief Return the length of the buffer in OT units + /// @return Length in OT units rounded up + /// @tparam OT the type to get the length of. For example, if one + /// wanted the length in double words, OT would be uint64_t + /// (getLength<uint64_t>().) Similarly, to get the length in words, + /// getLength<uin32_t>(). + /// + template< typename OT > + inline constexpr uint32_t getLength(void) const + { + return bufferTraits<T>::template size<OT>(this->iv_data); + } + + /// + /// @brief Templated setBit for integral types + /// @tparam B the bit number to set. + /// @return buffer& Useful for method chaining + /// @note 0 is left-most + /// @note Example: fapi2::buffer<uint64_t>().setBit<3>(); + /// + template <bits_type B> + inline buffer& setBit(void) + { + static_assert((B >= 0) && + (B < bufferTraits<T>::bits_per_unit), "failed range check"); + + // Force iv_data to be dependent on the template type to force + // its look up in the second phase + this->iv_data |= (static_cast<T>(1)) << (bufferTraits<T>::bits_per_unit - B - 1); + return *this; + } + + /// + /// @brief Clear a bit in buffer + /// @tparam B Bit in buffer to clear. + /// @return buffer& Useful for method chaining + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template< bits_type B > + inline buffer& clearBit(void) + { + static_assert((B >= 0) && + (B < bufferTraits<T>::bits_per_unit), "failed range check"); + + this->iv_data &= buffer<T>().setBit<B>().invert(); + return *this; + } + + /// + /// @brief Invert bit + /// @tparam B Bit in buffer to invert. + /// @return buffer& Useful for method chaining + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template< bits_type B > + inline buffer& flipBit(void) + { + static_assert((B >= 0) && + (B < bufferTraits<T>::bits_per_unit), "failed range check"); + + this->iv_data ^= buffer<T>().setBit<B>(); + return *this; + } + + /// + /// @brief Set a bit in the buffer + /// @param[in] i_bit the bit number to set. + /// @note 0 is left-most + /// @return FAPI2_RC_SUCCESS if OK + /// + inline fapi2::ReturnCode setBit(const bits_type& i_bit) + { + if (i_bit >= bufferTraits<T>::bits_per_unit) + { + return FAPI2_RC_INVALID_PARAMETER; + } + + // Force iv_data to be dependent on the template type to force + // its look up in the second phase + this->iv_data |= + (static_cast<T>(1)) << (bufferTraits<T>::bits_per_unit - i_bit - 1); + return FAPI2_RC_SUCCESS; + } + + /// + /// @brief Get the value of a bit in the buffer + /// @tparam B Bit in buffer to get. + /// @return true if bit is on, false if bit is off + /// + template< bits_type B > + inline bool getBit(void) const + { + return buffer<T>().setBit<B>() & this->iv_data; + } + + ///@} + + /// @name Buffer Manipulation Functions + ///@{ + + // Note: Many (all?) of these are not needed and the compiler complains + // as the cast to T yields a better operator. There are here mainly for + // documenation purposes. + + /// + /// @brief operator>>() + /// +#ifdef DOXYGEN + buffer<T>& operator>>(bits_type i_shiftnum); +#endif + + /// + /// @brief operator<<() + /// +#ifdef DOXYGEN + buffer<T>& operator<<(bits_type i_shiftnum); +#endif + + /// + /// @brief operator+() + /// +#ifdef DOXYGEN + buffer<T>& operator+(const T& rhs); +#endif + + /// + /// @brief operator+=() + /// +#ifdef DOXYGEN + buffer<T>& operator+=(const T& rhs); +#endif + + /// + /// @brief operator|=() + /// +#ifdef DOXYGEN + buffer<T>& operator|=(const T& rhs); +#endif + + /// + /// @brief operator&=() + /// +#ifdef DOXYGEN + buffer<T>& operator&=(const T& rhs); +#endif + + /// + /// @brief operator|() + /// +#ifdef DOXYGEN + buffer<T>& operator|(const T& rhs); +#endif + + /// + /// @brief operator&() + /// +#ifdef DOXYGEN + buffer<T>& operator&(const T& rhs); +#endif + + /// + /// @brief operator^=() + /// +#ifdef DOXYGEN + buffer<T>& operator^=(const T& rhs); +#endif + + /// + /// @brief operator~() + /// +#ifdef DOXYGEN + buffer<T>& operator~(const T& rhs) const; +#endif + + /// + /// @brief operator==() + /// +#ifdef DOXYGEN + bool operator==(const T& rhs) const; +#endif + + /// + /// @brief operator!=() + /// +#ifdef DOXYGEN + bool operator!=(const T& rhs) const; +#endif + + /// + /// @brief Copy part of a OT into the DataBuffer + /// @tparam TS Start bit to insert into (target start) + /// @tparam L Length of bits to insert + /// @tparam SS Start bit in source + /// @tparam OT the type of the incoming (origin) data + /// @param[in] i_datain OT value to copy into DataBuffer + /// - data is taken left aligned + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template<bits_type TS, bits_type L, bits_type SS, typename OT> + inline void insert(const OT i_datain) + { + const bits_type target_length = parameterTraits<T>::bit_length; + const bits_type source_length = parameterTraits<OT>::bit_length; + + // Error if input data don't make sense + static_assert((TS + L) <= target_length, + "insert(): (Target Start + Len) is out of bounds"); + static_assert((SS + L) <= source_length, + "insert(): (Source Start + Len) is out of bounds"); + static_assert(TS < target_length, + "insert(): Target Start is out of bounds"); + static_assert(SS < source_length, + "insert(): Source Start is out of bounds"); + + // Get mask value for Target buffer + // Note: Need "& ((T)-1) because bit shift left for Target buffer doesn't roll off + T mask =((T(~0) << (target_length - L)) & T(~0)) >> TS; + + // Calculate the equivalent position of the input Source start for the size of the Target buffer. + + // Assume OT is smaller (sizeof(T) > sizeof(OT)) + uint64_t sourceShift = abs(TS - ((target_length - source_length) + SS)); + uint64_t sourceAlign = T(i_datain) << sourceShift; + + if (sizeof(T) == sizeof(OT)) + { + sourceShift = abs(SS - TS); + sourceAlign = (SS > TS) ? ((T)i_datain) << sourceShift : ((T)i_datain) >> sourceShift; + } + + if (sizeof(T) < sizeof(OT)) + { + sourceShift = source_length - target_length; + if (SS <= sourceShift) + { + sourceShift = sourceShift + TS - SS; + sourceAlign = ((OT)i_datain) >> sourceShift; + } + + // (SS > sourceShift) + else + { + if (sourceShift > TS) + { + sourceShift = SS - sourceShift - TS; + sourceAlign = OT(i_datain) << sourceShift; + } + else + { + sourceShift = SS - sourceShift; + sourceAlign = (sourceShift < TS) ? OT(i_datain) >> sourceShift : OT(i_datain); + } + } + } + + this->iv_data = (this->iv_data & ~mask) | (sourceAlign & mask); + return; + } + + /// + /// @brief Copy in a right aligned value + /// @tparam SB Start bit to insert into + /// @tparam L Length of bits to insert + /// @tparam OT the type of the incoming (origin) data + /// @param[in] i_datain OT value to copy into DataBuffer + /// - data is taken right aligned + /// @note Data is assumed to be aligned on the word boundary of L + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template<bits_type TS, bits_type L, typename OT> + inline void insertFromRight(const OT i_datain) + { + // Error if input data don't make sense + static_assert(L <= parameterTraits<OT>::bit_length, + "insertFromRight(): Len >= input buffer"); + static_assert(TS < parameterTraits<T>::bit_length, + "insertFromRight(): Target Start is out of bounds"); + static_assert((TS + L) <= parameterTraits<T>::bit_length, + "InsertFromRight(): (Target Start + Len) is out of bounds"); + + this->insert<TS, L, parameterTraits<OT>::bit_length - L>(i_datain); + return; + } + + /// + /// @brief Copy data from this buffer into an OT + /// @tparam TS Start bit to insert into (target start) + /// @tparam L Length of bits to insert + /// @tparam SS Start bit in source + /// @tparam OT the type of the outgoing (target) + /// @param[out] o_out OT to copy into - data is placed left aligned + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template<bits_type TS, bits_type L, bits_type SS, typename OT> + inline void extract(OT& o_out) + { + // Extraction is just an insert into o_out + + buffer<OT> out(o_out); + out.insert<TS, L, SS>(this->iv_data); + o_out = out; + return; + } + +#if 0 + /// + /// @brief Copy data from this buffer into an OT and right justify + /// @tparam OT the type of the outgoing data - defaults to T + /// @tparam SB Start bit to insert into - defaults to 0 + /// @tparam SS Start bit in o_out - default value is zero + /// @tparam L Length of bits to copy - defaults to sizeof(OT) * 8 + /// @param[out] o_out OT to copy into - data is placed right aligned + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// @post Data is copied from specified location to o_out, right + /// aligned. Data is only right aligned if L < sizeof(bits_type) + /// + template< typename OT = T, bits_type L = parameterTraits<OT>::bit_length, + bits_type SB = 0, bits_type SS = 0 > + void extractFromRight(OT& o_out); +#endif + ///@} + }; +}; + +#endif diff --git a/src/ppe/hwpf/plat/include/buffer_parameters.H b/src/ppe/hwpf/plat/include/buffer_parameters.H new file mode 100644 index 0000000..c34686e --- /dev/null +++ b/src/ppe/hwpf/plat/include/buffer_parameters.H @@ -0,0 +1,65 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/buffer_parameters.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file buffer_parameters.H + * @brief definitions for fapi2 buffer parameter types + */ + +#ifndef __FAPI2_BUFFER_PARAM__ +#define __FAPI2_BUFFER_PARAM__ + +#include <stdint.h> + +namespace fapi2 +{ + /// @cond + /// @brief Traits of buffer parameters - things passed in + /// @tparam T is the type of i_value (typically an integral type) + template<typename T> + class parameterTraits + { + public: + enum + { + mask = T(~0), + bit_length = sizeof(T) * 8, + byte_length = sizeof(T), + }; + + template<typename U> + inline static void write_element(void* i_data, T i_value, uint32_t i_offset) + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + T* ptr = (T*)i_data + (i_offset ^ ((sizeof(U) / sizeof(T)) - 1)); +#else + T* ptr = (T*)i_data + i_offset; +#endif + *ptr = i_value; + } + }; + /// @endcond +}; + +#endif diff --git a/src/ppe/hwpf/plat/include/buffer_traits.H b/src/ppe/hwpf/plat/include/buffer_traits.H new file mode 100644 index 0000000..cfc699b --- /dev/null +++ b/src/ppe/hwpf/plat/include/buffer_traits.H @@ -0,0 +1,238 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/buffer_traits.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file buffer_traits.H + * @brief trait definitions for fapi2 buffer base class + */ + +#ifndef __FAPI2_BUFFER_TRAITS__ +#define __FAPI2_BUFFER_TRAITS__ + +#include <stdint.h> +#include <vector> +#include <algorithm> +#include <buffer_parameters.H> + +#ifdef __FAPI2_DEBUG__ +// for debug printing ... can be removed for flight +#include <iostream> +#endif +#include <iterator> + +namespace fapi2 +{ + /// @cond + /// Types representing a container of bits. Used to create + /// variable_buffer. + typedef uint32_t container_unit; + typedef std::vector<container_unit> bits_container; + + /// @brief Traits of buffers + // In general, we try to give buffers traits reflecting integral types. If + // this fails, the compiler will let someone know. + /// + /// @tparam T is the type of iv_data (std::vector, etc) + /// @tparam B is the type of the bit-specifier, typically uint32_t + template<typename T, typename B = uint32_t> + class bufferTraits + { + public: +#ifndef DOXYGEN +#ifdef __FAPI2_DEBUG__ + /// + /// @brief Print a container of bits + /// @param[in] i_data the container of bits + /// + static inline void print(const T& i_data) + { + // convert to uint64_t to prevent uint8_t from being + // printed as a char. + std::cout << "\tdata is " + << std::hex + << static_cast<uint64_t>(i_data) + << std::dec << std::endl; + } +#endif +#endif + + /// + /// @brief Return the size of the buffer in E units + /// @tparam E, the element size. + /// @param[in] io_buffer the buffer which to size + /// @return The size of the buffer in E's rounded up + /// + template<typename E> + constexpr static B size(const T& i_buffer) + { + return (bit_length(i_buffer) + + (parameterTraits<E>::bit_length - 1)) / + parameterTraits<E>::bit_length; + } + + /// + /// @brief Return the size of the buffer itself + /// @param[in] io_buffer the buffer which to size + /// @return The size of the buffer in bits (not units) + /// + constexpr static B bit_length(const T&) + { return sizeof(T) * 8; } + + /// + /// @brief Clear the buffer + /// @param[in,out] io_buffer the buffer which to clear + /// + static inline void clear(T& io_buffer) + { io_buffer = static_cast<T>(0); } + + /// + /// @brief Set the buffer + /// @param[in,out] io_buffer the buffer which to set + /// + static inline void set(T& io_buffer) + { io_buffer = static_cast<T>(~0); } + + /// + /// @brief Invert the buffer + /// @param[in,out] io_buffer the buffer which to invert + /// + static inline void invert(T& io_buffer) + { io_buffer = ~io_buffer; } + + /// + /// @brief Reverse the buffer + /// @param[in,out] io_buffer the buffer which to reverse + /// + static inline void reverse(T& io_buffer) + { + io_buffer = + ((io_buffer & 0xAAAAAAAAAAAAAAAA) >> 1) | + ((io_buffer & 0x5555555555555555) << 1); + } + + /// + /// @brief Get the address of the buffer as an array + /// @param[in] i_buffer the buffer which to invert + /// @return The address of the first element of the buffer + /// + static inline void* get_address(T& i_buffer) + { return (void*)&i_buffer; } + + typedef B bits_type; + typedef T unit_type; + enum { bits_per_unit = sizeof(unit_type) * 8 }; + }; + + // + // + /// @brief Traits for buffers which are a container of bits + // + // + template<> + class bufferTraits<bits_container, uint32_t> + { + public: +#ifndef DOXYGEN +#ifdef __FAPI2_DEBUG__ + /// + /// @brief Print a container of bits + /// @param[in] i_data the container of bits + /// + static inline void print(const bits_container& i_data) + { + std::cout << "\tdata is " << std::hex; + std::copy(i_data.begin(), i_data.end(), + std::ostream_iterator<container_unit>(std::cout, " ")); + std::cout << std::dec << std::endl; + } +#endif +#endif + + /// + /// @brief Return the size of the buffer in E units + /// @tparam E, the element size. + /// @param[in] io_buffer the buffer which to size + /// @return The size of the buffer in E's rounded up + /// + template<typename E> + constexpr static uint32_t size(const bits_container& i_buffer) + { + return (bit_length(i_buffer) + + (parameterTraits<E>::bit_length - 1)) / + parameterTraits<E>::bit_length; + } + + /// + /// @brief Return the size of the buffer itself + /// @param[in,out] io_buffer the buffer which to size + /// @return The size of the buffer in bits (not units) + /// + static inline uint32_t bit_length(const bits_container& i_buffer) + { return i_buffer.size() * sizeof(container_unit) * 8; } + + /// + /// @brief Clear the buffer + /// @param[in,out] io_buffer the buffer which to clear + /// + static inline void clear(bits_container& io_buffer) + { io_buffer.assign(io_buffer.size(), 0); } + + /// + /// @brief Set the buffer + /// @param[in,out] io_buffer the buffer which to set + /// + static inline void set(bits_container& io_buffer) + { io_buffer.assign(io_buffer.size(), ~0); } + + /// + /// @brief Invert the buffer + /// @param[in,out] io_buffer the buffer which to invert + /// + static inline void invert(bits_container& io_buffer) + { + std::transform(io_buffer.begin(), io_buffer.end(), + io_buffer.begin(), + [](container_unit u) { return ~u; }); + } + + /// + /// @brief Get the address of the buffer as an array + /// @param[in] i_buffer the buffer which to invert + /// @return The address of the first element of the buffer + /// + static inline void* get_address(bits_container& i_buffer) + { + return (void*)&(i_buffer[0]); + } + + typedef uint32_t bits_type; + typedef container_unit unit_type; + enum { bits_per_unit = sizeof(unit_type) * 8 }; + }; + /// @endcond +}; + + + +#endif diff --git a/src/ppe/hwpf/plat/include/error_scope.H b/src/ppe/hwpf/plat/include/error_scope.H new file mode 100644 index 0000000..173b6d1 --- /dev/null +++ b/src/ppe/hwpf/plat/include/error_scope.H @@ -0,0 +1,147 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/error_scope.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file error_scope.H + * @brief definitions which create a scope for automatic error handling + */ + +#ifndef __FAPI2_ERROR_SCOPE__ +#define __FAPI2_ERROR_SCOPE__ + +#include <stdint.h> +#include <thread> +#include <stdio.h> +#include <return_code.H> +#include <plat_includes.H> + + +extern "C" +{ +#ifndef __noRC__ + extern fapi2::ReturnCode G_current_err; +#endif + extern uint64_t G_pib_error_mask; + extern uint64_t G_operational_state; +} + + +/// +/// @brief Place holder until more of the FAPI infrastructure +/// can be compiled with this file +/// @param[in] ... varargs, passed to a platform specific output function +/// @note This is skeleton implementation for prototype purposes. This +/// does not imply "printf" is used on any or all platforms. +/// +#define FAPI_INF( ... ) +#define FAPI_ERR( ... ) PK_TRACE( __VA_ARGS__ ) +//#define FAPI_DBG( ... ) PK_TRACE( __VA_ARGS__ ) +#define FAPI_DBG( ... ) + +/// @cond +#define FAPI_VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N +#define FAPI_VA_NARGS(...) FAPI_VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1) + +//#define FAPI_TRY_IMPL2(...) FAPI_TRY_TRACE (__VA_ARGS__) +#define FAPI_TRY_IMPL2(count, ...) FAPI_TRY ## count (__VA_ARGS__) +#define FAPI_TRY_IMPL(count, ...) FAPI_TRY_IMPL2(count, __VA_ARGS__) + +#ifndef __noRC__ +#define FAPI_TRY_NO_TRACE( __operation__ ) \ + if ((fapi2::current_err = (__operation__)) != fapi2::FAPI2_RC_SUCCESS) \ + { \ + goto clean_up; \ + } +#else +#define FAPI_TRY_NO_TRACE( __operation__ ) \ + (__operation__); +#endif + +// Why debug? Because this isn't a mechanism to gather FFDC +// one should be using FAPI_ASSERT. However, it is nice to +// have a conditional trace in the event of a failure in the +// operation, so that's why this is here. +// if ((fapi2::current_err = (__operation__)) != fapi2::FAPI2_RC_SUCCESS) +#ifndef __noRC__ +#define FAPI_TRY_TRACE( __operation__, ... ) \ + if ((fapi2::current_err = (__operation__)) != fapi2::FAPI2_RC_SUCCESS) \ + { \ + FAPI_DBG(__VA_ARGS__); \ + goto clean_up; \ + } +#define FAPI_CLEANUP() \ +clean_up: +#else +/// @todo: something is wrong needed the goto_cleanup +#define FAPI_TRY_TRACE( __operation__, ... ) \ + FAPI_DBG(__VA_ARGS__); \ + (__operation__) + +#define FAPI_CLEANUP() + +#endif + +#define FAPI_TRY0 FAPI_TRY_NO_TRACE +#define FAPI_TRY1 FAPI_TRY_TRACE +#define FAPI_TRY2 FAPI_TRY_TRACE +#define FAPI_TRY3 FAPI_TRY_TRACE +#define FAPI_TRY4 FAPI_TRY_TRACE +#define FAPI_TRY5 FAPI_TRY_TRACE +/// @endcond + +/// +/// @brief Wrapper to check an operation for an error state +/// and jump to the label cleam_up if there is an error. +/// @param[in] __operation__ an operation which returns a fapi::ReturnCode +/// @param[in] Optional vararg format/agruments for trace output. +/// @note This implementation does not support PIB error masks or +/// FSP operational states. +/// @warning The trace information is only going to be seen during +/// debug, it's not an error or informational trace. This is because +/// traces might not be seen in the field. If you want information +/// you will see on a field error, use FAPI_ASSERT. +/// +#ifdef DOXYGEN +#define FAPI_TRY(__operation__, ...) FAPI_TRY_IMPL +#else +#define FAPI_TRY(...) FAPI_TRY_IMPL(FAPI_VA_NARGS(__VA_ARGS__), __VA_ARGS__) +#endif + +/// +/// @brief Assert a conditional is true. +/// If it is not, the FFDC gathering function is called and the +/// trace is output as a FAPI error trace. +/// @param[in] __conditional__ the condition to assert +/// @param[in] __ffdc__ the FFDC gathering function +/// @param[in] ... varargs, as input to FAPI_ERR +/// +#define FAPI_ASSERT( __conditional__, __ffdc__, ... ) \ + if (! (__conditional__)) \ + { \ + /* __ffdc__; */ \ + FAPI_ERR(__VA_ARGS__); \ + goto clean_up; \ + } + +#endif // __FAPI2_ERROR_SCOPE__ diff --git a/src/ppe/hwpf/plat/include/fapi2.H b/src/ppe/hwpf/plat/include/fapi2.H new file mode 100644 index 0000000..17d3d59 --- /dev/null +++ b/src/ppe/hwpf/plat/include/fapi2.H @@ -0,0 +1,76 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/fapi2.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// +/// @file fapi2.H +/// @brief top level header for fapi2 +/// + +#ifndef __FAPI2_TOP_LEVEL__ +#define __FAPI2_TOP_LEVEL__ + +// Define which platforms will not have FAPI Return Codes +#undef __noRC__ +#if defined (__CME__) || defined (__SGPE__) || defined (__PGPE__) +#define __noRC__ +#endif + +// Determine if running on a PPE platform +#ifndef __PPE__ +#if defined (__SBE__) || defined (__CME__) || defined (__SGPE__) || defined (__PGPE__) +#define __PPE__ +#endif +#endif + +#include <plat_trace.H> +#include <target.H> +#include <return_code.H> +#include <buffer.H> +#include <hw_access.H> +#include <utils.H> + + +// In turn includes the needed generated headers (hwp_ffd_classes, etc.) +#include <error_scope.H> +//#include <set_sbe_error.H> // Generated file mb empty file addCopyright.pl does not like empty files +#include <fapi2AttributeService.H> +#include <fapi2AttributeIds.H> // Generated file + + +// #include <hwp_executor.H> // mb empty file addCopyright.pl does not like empty files + +// Block of headers not currently in fapi2 +#ifdef FAPI2_MISSING_HEADERS + #include <mvpdAccess.H> + #include <mbvpdAccess.H> +#endif + + +#endif // __FAPI2_TOP_LEVEL__ + + + + + + diff --git a/src/ppe/hwpf/plat/include/fapi2Structs.H b/src/ppe/hwpf/plat/include/fapi2Structs.H new file mode 100644 index 0000000..c13b428 --- /dev/null +++ b/src/ppe/hwpf/plat/include/fapi2Structs.H @@ -0,0 +1,133 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/fapi2Structs.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef fapiStructs_h +#define fapiStructs_h +// Copyright ********************************************************** +// +// File fapiStructs.H +// +// IBM Confidential +// OCO Source Materials +// 9400 Licensed Internal Code +// (C) COPYRIGHT IBM CORP. 1996 +// +// 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. +// +// End Copyright ****************************************************** + +/** + * @file fapiStructs.H + * @brief fapi eCMD Extension Structures + + * Extension Owner : John Farrugia +*/ + +//-------------------------------------------------------------------- +// Includes +//-------------------------------------------------------------------- +#include <string> + + +//-------------------------------------------------------------------- +// Forward References +//-------------------------------------------------------------------- + +#define ECMD_FAPI_CAPI_VERSION "1.0" ///< eCMD FAPI Extension version + + + +#ifndef ECMD_PERLAPI + +namespace fapi +{ + +/** + * @brief Enumeration of fapi file types + */ +typedef enum { + FAPI_FILE_UNKNOWN, ///< Default for not initialized + FAPI_FILE_HWP +} FileType_t; + + +enum AttributeSource +{ + FAPI_ATTRIBUTE_SOURCE_UNKNOWN = 0x00000000, + FAPI_ATTRIBUTE_SOURCE_PLAT = 0x00000001, + FAPI_ATTRIBUTE_SOURCE_HWP = 0x00000002, +}; + + +#define FAPI_ATTRIBUTE_TYPE_STRING 0x80000000 +#define FAPI_ATTRIBUTE_TYPE_UINT8 0x40000000 +#define FAPI_ATTRIBUTE_TYPE_UINT32 0x20000000 +#define FAPI_ATTRIBUTE_TYPE_UINT64 0x10000000 +#define FAPI_ATTRIBUTE_TYPE_UINT8ARY 0x04000000 +#define FAPI_ATTRIBUTE_TYPE_UINT32ARY 0x02000000 +#define FAPI_ATTRIBUTE_TYPE_UINT64ARY 0x01000000 + +#define FAPI_ATTRIBUTE_MODE_CONST 0x80000000 +/** + @brief Used by the get/set configuration functions to return the data +*/ +template<typename T> +class Attribute +{ +public: + // Constructor + Attribute(); + + // Destructor + ~Attribute(); + + // + /// @brief Assignment Operator. + /// @param[in] i_right Reference to Value to assign from. + /// @return Reference to 'this' Target + /// + Attribute<T>& operator=(const T& i_right) + { + this->value = i_right->value; + } + +private: + T value; + +}; + +inline AttributeData::AttributeData() {} + +inline AttributeData::~AttributeData() {} + +} //namespace +#endif // #ifndef ECMD_PERLAPI +#endif + + + + + diff --git a/src/ppe/hwpf/plat/include/hw_access.H b/src/ppe/hwpf/plat/include/hw_access.H new file mode 100644 index 0000000..758f035 --- /dev/null +++ b/src/ppe/hwpf/plat/include/hw_access.H @@ -0,0 +1,606 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/hw_access.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file hw_access.H + * + * @brief Defines the hardware access functions for PPE platforms that + * don't leverage FAPI2 return codes. + */ + +#ifndef FAPI2_HWACCESS_H_ +#define FAPI2_HWACCESS_H_ + + +// variable_buffer isn't supported on PPE +#ifndef __PPE__ +#include <variable_buffer.H> +#endif + +#include <plat_hw_access.H> +#include <fapi2_hw_access.H> + +namespace fapi2 +{ + + //-------------------------------------------------------------------------- + // PIB Error Functions + //-------------------------------------------------------------------------- + + /// @brief Sets the PIB error mask - platform dependant + /// @param[in] i_mask The new error mask + void setPIBErrorMask(uint8_t i_mask) + { + PLAT_SET_PIB_ERROR_MASK(i_mask); + } + + /// @brief Gets the PIB error mask - platform dependant + /// @return uint8_t The current PIB error mask + uint8_t getPIBErrorMask(void) + { + uint8_t o_pib_mask; + PLAT_GET_PIB_ERROR_MASK(o_pib_mask); + return o_pib_mask; + } + + //-------------------------------------------------------------------------- + // Operational Mode Error Functions + //-------------------------------------------------------------------------- + + /// @brief Sets the operational mode + /// @param[in] i_mode The new mode + // note: this can be moved to a C file if desired + inline void setOpMode(const OpModes i_mode) + { + // Keeps the compiler from complaining about the unused i_mode + static_cast<void>(i_mode); + + // No-op for now. Should set thread-local operational mode + return; + } + + /// @brief Gets the operational mode + /// @return the operational mode + // note: this can be moved to a C file if desired + inline OpModes getOpMode(void) + { + // No-op for now. Should read thread-local operational mode + return NORMAL; + } + + //-------------------------------------------------------------------------- + // HW Communication Functions + //-------------------------------------------------------------------------- + + /// @brief Reads a SCOM register from a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address SCOM register address to read from. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline void getScom(const Target<K>& i_target, const uint64_t i_address, + buffer<uint64_t>& o_data) + { + // PLAT_GETSCOM(i_target, +// (uint32_t)(i_address & BITS(40,24)), +// &(o_data())); + +// fapi2::ReturnCode l_rc; + PLAT_GETSCOM(current_err, + i_target, + (uint32_t)(i_address & BITS(40,24)), + &(o_data())); + } + + + /// @brief Writes a SCOM register on a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address SCOM register address to write to. + /// @param[in] i_data Buffer that holds data to write into address. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline void putScom(const Target<K>& i_target, const uint64_t i_address, + buffer<uint64_t>& i_data) + { + + PLAT_PUTSCOM(i_target, + (uint32_t)(i_address & BITS(40,24)), + &(i_data())); + } + + /// @brief Read-modify-write a SCOM register on a chip + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address SCOM register address to write to. + /// @param[in] i_data Buffer that holds data to be modified. + /// @param[in] i_modifyMode The modify mode (or/and/xor). + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline void modifyScom( const Target<K>& i_target, + const uint64_t i_address, + const buffer<uint64_t>& i_data, + const ChipOpModifyMode i_modifyMode) + { + fapi2::buffer<uint64_t> l_modifyDataBuffer; + + PLAT_GETSCOM(i_target, + (uint32_t)(i_address & BITS(40,24)), + &(l_modifyDataBuffer())); + + if ( i_modifyMode == CHIP_OP_MODIFY_MODE_OR) + { + l_modifyDataBuffer |= i_data; + } + + if ( i_modifyMode == CHIP_OP_MODIFY_MODE_AND) + { + l_modifyDataBuffer &= i_data; + } + + if ( i_modifyMode == CHIP_OP_MODIFY_MODE_XOR) + { + l_modifyDataBuffer ^= i_data; + } + + PLAT_PUTSCOM(i_target, + (uint32_t)(i_address & BITS(40,24)), + &(l_modifyDataBuffer())); + return; + } + + /// @brief Writes a SCOM register under mask on a chip + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address SCOM register address to write to. + /// @param[in] i_data Buffer that holds data to write into address. + /// @param[in] i_mask Buffer that holds the mask value. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline void putScomUnderMask(const Target<K>& i_target, + const uint64_t i_address, + buffer<uint64_t>& i_data, + buffer<uint64_t>& i_mask) + { + fapi2::buffer<uint64_t> l_modifyDataBuffer = i_data; + + l_modifyDataBuffer &= i_mask; + + PLAT_PUTSCOM(i_target, + (uint32_t)(i_address & BITS(40,24)), + &(l_modifyDataBuffer())); + return; + } + + + /// @brief Reads a CFAM register from a chip. + /// CFAM register is 32-bit wide. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address CFAM register address to read from. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode getCfamRegister(const Target<K>& i_target, + const uint32_t i_address, + buffer<uint32_t>& o_data) + { + PLAT_GETCFAM(i_target.get(), + (uint32_t)(i_address & BITS(40,24)), + &(o_data())); + + return FAPI2_RC_SUCCESS; + } + + /// @brief Writes a CFAM register on a chip. + /// CFAM register is 32-bit wide. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address CFAM register address to write to. + /// @param[in] i_data Buffer that holds data to write into address. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode putCfamRegister(const Target<K>& i_target, + const uint32_t i_address, + buffer<uint32_t>& i_data) + { + PLAT_PUTCFAM(i_target.get(), + (uint32_t)(i_address & BITS(40,24)), + &(i_data())); + + return FAPI2_RC_SUCCESS; + } + + /// @brief Read-modify-write a CFAM register on a chip. + /// CFAM register is 32-bit wide. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address CFAM register address to modify. + /// @param[in] i_data Buffer that holds data to be modified. + /// @param[in] i_modifyMode The modify mode (or/and/xor). + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode modifyCfamRegister(const Target<K>& i_target, + const uint32_t i_address, + const buffer<uint32_t>& i_data, + const ChipOpModifyMode i_modifyMode) + { + PLAT_MODCFAM(i_target.get(), + (uint32_t)(i_address & BITS(40,24)), + &(i_data()), + i_modifyMode); + + return FAPI2_RC_SUCCESS; + } + + // variable_buffer isn't supported on PPE +#ifndef __PPE__ + /// @brief Reads a ring from a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_address Ring address to read from. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @param[in] i_ringMode Ring operation mode. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode getRing(const Target<K>& i_target, + const scanRingId_t i_address, + variable_buffer& o_data, + const RingMode i_ringMode = 0) + { + o_data.setBit(0); + o_data.setBit(3); +#ifndef __PPE__ + std::cout << std::hex << " getRing " + << "target: {" << i_target.getType() << "," + << uint64_t(i_target) << "}; " + << "ring address: " << i_address << "; " + << "ring mode: " << i_ringMode << "; " + << "output data:"; + o_data.print(); +#endif + + return FAPI2_RC_SUCCESS; + } + + /// @brief Writes a ring to a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_address Ring address to write to. + /// @param[in] i_data Buffer that contains RS4 compressed ring data + /// to write into address + /// @param[in] i_ringMode Ring operation mode. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode putRing(const Target<K>& i_target, + const scanRingId_t i_address, + variable_buffer& i_data, + const RingMode i_ringMode = 0) + { + + return FAPI2_RC_SUCCESS; + } + + + /// @brief Writes a ring to a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_address Ring address to write to. + /// @param[in] i_data Pointer to location that contains RS4 compressed + // ring data to write into address + /// @param[in] i_ringMode Ring operation mode. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode putRing(const Target<K>& i_target, + const scanRingId_t i_address, + const void* i_data, + const RingMode i_ringMode = 0) + { + uint64_t* dataPtr = reinterpret_cast<uint64_t*>(const_cast<void*>(i_data)); + + return FAPI2_RC_SUCCESS; + } + + /// @brief Read-modify-write a ring on a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_address Ring address to modify. + /// @param[in] i_data Buffer that contains RS4 compressed ring data + /// to be modified. + /// @param[in] i_modifyMode The modify mode (or/and/xor) + /// @param[in] i_ringMode Ring operation mode. + /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode modifyRing(const Target<K>& i_target, + const scanRingId_t i_address, + variable_buffer& i_data, + const ChipOpModifyMode i_modifyMode, + const RingMode i_ringMode = 0) + { + + return FAPI2_RC_SUCCESS; + } +#endif + + +#ifdef FAPI_SUPPORT_MULTI_SCOM + /// @brief Performs a multiple SCOM operation + /// This interface performs multiple SCOM operations on a chip in the + /// order specified by the input MultiScom object. + /// See fapiMultiScom.H for details of how to populate the MultiScom + /// object with SCOM operations. + /// + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in,out] io_multiScomObj Reference to a MultiScom object, + /// pre-populated with SingleScomInfo entries + /// to perform multiple SCOMs on input target + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note This is a synchronous interface and would return after all the + /// SCOM operations are completed or on the first failed operation + /// + /// @note SCOMs will be performed in the order they were added to the + /// input MultiScom object + /// + /// @note In case of errors, the platform code is responsible to collect + /// and add all the required error info and FFDC into the error data + /// for debugging + /// + /// @note If the SCOM operations added are specific to a processor chip, + /// then the FSI Shift Engine configured in scatter-gather DMA mode + /// extension would be used to execute the SCOM operations in a + /// performance optimize mode. In this mode, the special + /// SCOM_BULK_READ_MODE and SCOM_BULK_WRITE_MODE operations are + /// supported that allow a large bulk of SCOM access (in multiple of + /// 64 bits) for targets that support auto-increment. The + /// SCOM_WRITE_UNDER_MASK operation is not supported in this mode + /// + /// @note If the SCOM operations added are specific to a memory buffer + /// chip, then the regular SCOM engine is used to execute the SCOM + /// operations. SCOM_WRITE_UNDER_MASK operation is supported in + /// this mode, but the special SCOM_BULK_READ_MODE and + /// SCOM_BULK_WRITE_MODE operations are not supported due to + /// hardware limitations. + /// + template< TargetType K > + fapi2::ReturnCode multiScom (const Target<K>& i_target, + MultiScom& io_multiScomObj) + { + } +#endif + + // -------------------------------------------------------------------------- + // NOTE: + // Implement platform Spy access functions if platform supports them. + // -------------------------------------------------------------------------- + + // variable_buffer isn't supported on PPE +#ifndef __PPE__ + /// @brief Reads a spy from a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_spyId Id of the spy whose data to be read. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependant on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// 1. if the spy name contains a # procedure writers should replace + /// it with an __P__ for example - + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// becomes + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// 2. if the spy name has a number following a "." it must have an + /// underscore prepended to the number. + /// + /// EH.TPCHIP.2KX100_ARY_CLK_EDGES_DLY + /// becomes + /// EH.TPCHIP._2KX100_ARY_CLK_EDGES_DLY + /// + /// Example SPY name: + /// The hardware procedure should call the function like: + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// fapi2::ReturnCode rc = fapiGetSpy( targ, + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS, data ); + /// + /// @note The ID is not in quotes the fapi code will handle adding + /// the quotes for the cronus environment + /// +#ifdef FAPI_SUPPORT_SPY_AS_ENUM + template< TargetType K > + inline ReturnCode getSpy(const Target<K>& i_target, + const spyId_t i_spyId, + variable_buffer& o_data) + { + static_assert(K == 0, "implement getSpy (string)"); + return ~FAPI2_RC_SUCCESS; + } +#endif +#ifdef FAPI_SUPPORT_SPY_AS_STRING + template< TargetType K > + inline ReturnCode getSpy(const Target<K>& i_target, + const char * const i_spyId, + variable_buffer& o_data) + { + static_assert(K == 0, "implement getSpy (string)"); + return ~FAPI2_RC_SUCCESS; + } +#endif + /// @brief Writes a spy on a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_spyId Id of the spy to write data to. + /// @param[out] i_data Buffer that holds data to write into spy. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependent on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// 1. if the spy name contains a # procedure writers should replace + /// is with an __P__ for example - + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// becomes + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// 2. if the spy name has a number following a "." it must have an + /// underscore prepended to the number. + /// + /// EH.TPCHIP.2KX100_ARY_CLK_EDGES_DLY + /// becomes + /// EH.TPCHIP._2KX100_ARY_CLK_EDGES_DLY + /// + /// Example SPY name: + /// The hardware procedure should call the function like: + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// fapi2::ReturnCode rc = fapiPutSpy( targ, + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS, data ); + /// + /// @note The ID is not in quotes the fapi code will handle adding + /// the quotes for the cronus environment + /// +#ifdef FAPI_SUPPORT_SPY_AS_ENUM + template< TargetType K > + inline ReturnCode putSpy(const Target<K>& i_target, + const spyId_t i_spyId, + variable_buffer& i_data) + { + static_assert(K == 0, "implement putSpy (enum)"); + return ~FAPI2_RC_SUCCESS; + } +#endif +#ifdef FAPI_SUPPORT_SPY_AS_STRING + template< TargetType K > + inline ReturnCode putSpy(const Target<K>& i_target, + const char* const i_spyId, + variable_buffer& i_data) + { + static_assert(K == 0, "implement putSpy (string)"); + return ~FAPI2_RC_SUCCESS; + } +#endif + /// @brief Writes spy data into a buffer holding ring data image + /// This API is used by L2/L3 repair to put column repair data + /// into a ring buffer image. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_spyId Id of the spy. + /// @param[in] i_data Buffer that holds spy data to write into ring + /// image. + /// @param[out] o_data Buffer that holds updated ring image. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependent on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// See fapiPutSpy for details on spy id specifics. + /// +#ifdef FAPI_SUPPORT_SPY_AS_ENUM + template< TargetType K > + inline ReturnCode putSpyImage(const Target<K>& i_target, + const spyId_t i_spyId, + const variable_buffer& i_data, + variable_buffer& o_imageData) + { + static_assert(K == 0, "implement putSpyImage (enum)"); + return ~FAPI2_RC_SUCCESS; + } +#endif +#ifdef FAPI_SUPPORT_SPY_AS_STRING + template< TargetType K > + inline ReturnCode putSpyImage(const Target<K>& i_target, + const char* const i_spyId, + const variable_buffer& i_data, + variable_buffer& o_imageData) + { + static_assert(K == 0, "implement putSpyImage (string)"); + return ~FAPI2_RC_SUCCESS; + } +#endif + /// @brief Reads spy data from a ring image buffer + /// @param[in] i_target Target to operate on + /// @param[in] i_spyId The spy's id + /// @param[out] o_data Buffer that holds data read from ring image. + /// @param[in] i_imageData Buffer that holds ring image to read data + /// from. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependent on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// See fapiPutSpy for details on spy id specifics. + /// +#ifdef FAPI_SUPPORT_SPY_AS_ENUM + template< TargetType K > + inline ReturnCode getSpyImage(const Target<K>& i_target, + const spyId_t i_spyId, + variable_buffer& o_data, + const variable_buffer& i_imageData) + { + static_assert(K == 0, "implement getSpyImage (enum)"); + return ~FAPI2_RC_SUCCESS; + } +#endif +#ifdef FAPI_SUPPORT_SPY_AS_STRING + template< TargetType K > + inline ReturnCode getSpyImage(const Target<K>& i_target, + const char * const i_spyId, + variable_buffer& o_data, + const variable_buffer& i_imageData) + { + static_assert(K == 0, "implement getSpyImage (string)"); + return ~FAPI2_RC_SUCCESS; + } +#endif + +#endif // PPE + +}; + +#endif // _FAPI2_HWACCESS_H_ diff --git a/src/ppe/hwpf/plat/include/plat_hw_access.H b/src/ppe/hwpf/plat/include/plat_hw_access.H new file mode 100644 index 0000000..429ceff --- /dev/null +++ b/src/ppe/hwpf/plat/include/plat_hw_access.H @@ -0,0 +1,102 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/plat_hw_access.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/** + * @file plat_hw_access.H + * + * @brief Define platform specific calls for PPE Platforms that use the machine + * check function of the PPE to deal with errors (eg no explicit return codes + * returned) + */ + +#ifndef PLATHWACCESS_H_ +#define PLATHWACCESS_H_ + +#include <plat_includes.H> + +/// PIB Error Mask + +#define PLAT_SET_PIB_ERROR_MASK(_m_mask) \ + { /* Read MSR */ \ + uint32_t msr_data = mfmsr(); \ + /* Set SEM field */ \ + msr_data &= ~(BITS(0,8)); \ + msr_data |= (uint32_t)(i_mask << 24); \ + /* Write MSR */ \ + mtmsr(msr_data); \ + }; + +#define PLAT_GET_PIB_ERROR_MASK(_m_mask) \ + uint8_t _m_mask; \ + uint32_t _sem = mfmsr(); \ + _m_mask = (uint8_t)((_sem & MSR_SEM) >> (32-(MSR_SEM_START_BIT + MSR_SEM_LEN))); + +// Building block PPE instructions +#define PPE_MFMSR(_m_data) \ +asm volatile \ + ( \ + "mfmsr %[data] \n" \ + : [data]"=&r"(*_m_data) \ + : "[data]"(*_m_data) \ + ); + +#define PPE_MTMSR(_m_data) \ +asm volatile \ + ( \ + "mtmsr %[data] \n" \ + : [data]"=&r"(*_m_data) \ + : "[data]"(*_m_data) \ + ); + + +/// GetScom +#define PLAT_GETSCOM(_m_rc, _m_base, _m_offset, _m_data) \ + PPE_LVDX(_m_base.getAddressOverlay(), (uint32_t)(_m_offset & BITS(40,24)), _m_data) + +/// PutScom +#define PLAT_PUTSCOM(_m_base, _m_offset, _m_data) \ + PPE_STVDX(_m_rc, _m_base.getAddressOverlay(), (uint32_t)(_m_offset & BITS(40,24)), _m_data) + +/// ModifyScom +#define PLAT_MODSCOM(_m_base, _m_offset, _m_data, _m_mode) \ + PPE_STVDX(_m_base.getAddressOverlay(), _m_offset, _m_data) + + +/// GetCFAM +#define PLAT_GETCFAM(_m_base, _m_offset, _m_data) \ + static_assert( K == TARGET_TYPE_NONE, \ + "getCfamRegister is not supported by PPE platforms") + +/// PutCFAM +#define PLAT_PUTCFAM(_m_base, _m_offset, _m_data) \ + static_assert( K == TARGET_TYPE_NONE, \ + "putCfamRegister is not supported by PPE platforms") + +/// ModifyCFAM +#define PLAT_MODCFAM(_m_base, _m_offset, _m_data, _m_mode) \ + static_assert( K == TARGET_TYPE_NONE, \ + "modifyCfamRegister is not supported by PPE platforms") + +#endif // PLATHWACCESS_H_ + diff --git a/src/ppe/hwpf/plat/include/plat_includes.H b/src/ppe/hwpf/plat/include/plat_includes.H new file mode 100644 index 0000000..b549ca0 --- /dev/null +++ b/src/ppe/hwpf/plat/include/plat_includes.H @@ -0,0 +1,40 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/plat_includes.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file plat_includes.H + * @brief Platform specific include to implement FAPI2 APIs + */ + +#ifndef __PLAT_INCLUDES_H__ +#define __PLAT_INCLUDES_H__ + +#include <plat_hw_access.H> + +#include <ppe42_scom.h> +#include <ppe42_msr.h> +//#include <pk.h> + + +#endif // __PLAT_INCLUDES_H__ diff --git a/src/ppe/hwpf/plat/include/plat_target.H b/src/ppe/hwpf/plat/include/plat_target.H new file mode 100644 index 0000000..a9c1866 --- /dev/null +++ b/src/ppe/hwpf/plat/include/plat_target.H @@ -0,0 +1,43 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/plat_target.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file plat_target.H + * @brief platform definitions for fapi2 targets + */ + +#ifndef __FAPI2_PLAT_TARGET__ +#define __FAPI2_PLAT_TARGET__ + +// +// Define what a platform handle looks like. For Hostboot, +// for example, this might be a void*. For the SBE, this +// will be a uint64_t ... +// +namespace fapi2 +{ + typedef uint64_t plat_target_handle_t; +} + +#endif diff --git a/src/ppe/hwpf/plat/include/plat_target_definitions.H b/src/ppe/hwpf/plat/include/plat_target_definitions.H new file mode 100644 index 0000000..4056f92 --- /dev/null +++ b/src/ppe/hwpf/plat/include/plat_target_definitions.H @@ -0,0 +1,112 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/plat_target_definitions.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file plat_ppe_target.H + * @brief Definitions for fapi2 PPE targets + */ + +#ifndef __FAPI2_PPE_TARGET__ +#define __FAPI2_PPE_TARGET__ + +#define TARGET_CHIP(_name, _index) \ + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP > _name((uint64_t)_index); + +#define TARGET_CHIP_PERV(_name, _index) \ + fapi2::Target<fapi2::TARGET_TYPE_PERV> _name((uint64_t)_index); + +#define TARGET_EQ(_name, _index) \ + fapi2::Target<fapi2::TARGET_TYPE_EQ> _name((uint64_t)_index); + +#define TARGET_CORE(_name, _index) \ + fapi2::Target<fapi2::TARGET_TYPE_CORE> _name((uint64_t)_index); + +#define TARGET_EX(_name, _index) \ + fapi2::Target<fapi2::TARGET_TYPE_EX> _name((uint64_t)_index); + +namespace fapi2 +{ + + TARGET_CHIP (chip_target, 0); + TARGET_CHIP_PERV (perv_target, 1); + TARGET_CHIP_PERV (n0_target, 2); + TARGET_CHIP_PERV (n1_target, 3); + TARGET_CHIP_PERV (n2_target, 4); + TARGET_CHIP_PERV (n3_target, 5); + TARGET_CHIP_PERV (xb_target, 6); + TARGET_CHIP_PERV (mc0_target, 7); + TARGET_CHIP_PERV (mc1_target, 8); + TARGET_CHIP_PERV (ob0_target, 9); + TARGET_CHIP_PERV (ob1_target, 10); + TARGET_CHIP_PERV (ob2_target, 11); + TARGET_CHIP_PERV (ob3_target, 12); + TARGET_CHIP_PERV (pci0_target, 13); + TARGET_CHIP_PERV (pci1_target, 14); + TARGET_CHIP_PERV (pci2_target, 15); + TARGET_EQ (eq0_target, 0); + TARGET_EQ (eq1_target, 1); + TARGET_EQ (eq2_target, 2); + TARGET_EQ (eq3_target, 3); + TARGET_EQ (eq4_target, 4); + TARGET_EQ (eq5_target, 5); + TARGET_EX (ex0_target, 0); + TARGET_EX (ex1_target, 1); + TARGET_EX (ex2_target, 2); + TARGET_EX (ex3_target, 3); + TARGET_EX (ex4_target, 4); + TARGET_EX (ex5_target, 5); + TARGET_EX (ex6_target, 6); + TARGET_EX (ex7_target, 7); + TARGET_EX (ex8_target, 8); + TARGET_EX (ex9_target, 9); + TARGET_EX (ex10_target, 10); + TARGET_EX (ex11_target, 11); + TARGET_CORE (core0_target, 0); + TARGET_CORE (core1_target, 1); + TARGET_CORE (core2_target, 2); + TARGET_CORE (core3_target, 3); + TARGET_CORE (core4_target, 4); + TARGET_CORE (core5_target, 5); + TARGET_CORE (core6_target, 6); + TARGET_CORE (core7_target, 7); + TARGET_CORE (core8_target, 8); + TARGET_CORE (core9_target, 9); + TARGET_CORE (core10_target,10); + TARGET_CORE (core11_target,11); + TARGET_CORE (core12_target,12); + TARGET_CORE (core13_target,13); + TARGET_CORE (core14_target,14); + TARGET_CORE (core15_target,15); + TARGET_CORE (core16_target,16); + TARGET_CORE (core17_target,17); + TARGET_CORE (core18_target,18); + TARGET_CORE (core19_target,19); + TARGET_CORE (core20_target,20); + TARGET_CORE (core21_target,21); + TARGET_CORE (core22_target,22); + TARGET_CORE (core23_target,23); + +}; // fapi2 namespace + +#endif // __FAPI2_PPE_TARGET__ diff --git a/src/ppe/hwpf/plat/include/plat_target_parms.H b/src/ppe/hwpf/plat/include/plat_target_parms.H new file mode 100644 index 0000000..2c724a3 --- /dev/null +++ b/src/ppe/hwpf/plat/include/plat_target_parms.H @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/plat_target_parms.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file plat_ppe_target.H + * @brief Definitions for fapi2 PPE targets + */ + +#ifndef __FAPI2_PPE_TARGET_PARMS__ +#define __FAPI2_PPE_TARGET_PARMS__ + + +#ifndef __ASSEMBLER__ + +const uint64_t CHIPLET_COUNT = 0x38; + +const uint64_t CHIP_TARGET_COUNT = 1; +const uint64_t CHIP_TARGET_OFFSET = 0; + +const uint64_t PERV_TARGET_OFFSET = CHIP_TARGET_OFFSET + CHIP_TARGET_COUNT; +const uint64_t PERV_CHIPLET_OFFSET = 0x1; +const uint64_t PERV_TARGET_COUNT = 15; + +const uint64_t EQ_TARGET_OFFSET = PERV_TARGET_OFFSET + PERV_TARGET_COUNT; +const uint64_t EQ_CHIPLET_OFFSET = 0x10; +const uint64_t EQ_TARGET_COUNT = 6; + +const uint64_t CORE_TARGET_OFFSET = EQ_TARGET_OFFSET + EQ_TARGET_COUNT; +const uint64_t CORE_CHIPLET_OFFSET = 0x20; +const uint64_t CORE_TARGET_COUNT = 24; + +const uint64_t EX_TARGET_OFFSET = CORE_TARGET_OFFSET + CORE_TARGET_COUNT; +const uint64_t EX_CHIPLET_OFFSET = 0x10; +const uint64_t EX_TARGET_COUNT = 12; + + +const uint64_t TARGET_COUNT = EX_TARGET_OFFSET + EX_TARGET_COUNT; + +#endif + +#endif // __FAPI2_PPE_TARGET_PARMS__ diff --git a/src/ppe/hwpf/plat/include/plat_trace.H b/src/ppe/hwpf/plat/include/plat_trace.H new file mode 100644 index 0000000..d656d60 --- /dev/null +++ b/src/ppe/hwpf/plat/include/plat_trace.H @@ -0,0 +1,70 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/plat_trace.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,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 */ +/** + * @file plat_trace.H + * @brief Defines the FAPI2 trace macros. + * + * Note that platform code must provide the implementation. + * + * FAPI has provided a default implementation. Platform code must + * provide an alternate implementation if needed. + */ + +#ifndef FAPI2_PLATTRACE_H_ +#define FAPI2_PLATTRACE_H_ + +#include <stdio.h> +#include <stdint.h> + +// Why not a #define, why is this in the fapi2 namespace? +// To prevent problems with Cronus and the fapi1 definitions. +namespace fapi2 +{ + static const uint32_t MAX_ECMD_STRING_LEN = 64; +}; + +// Information traces (go into fast trace buffer that can wrap often) +#define FAPI_TRACE(_id_, _fmt_, _args_...) \ + printf("%s: %s:%d ", _id_, __func__, __LINE__); \ + printf(_fmt_, ##_args_); \ + printf("\n") + +#define FAPI_INF(_fmt_, _args_...) FAPI_TRACE("inf", _fmt_, ##_args_) + +// Important traces (go into slow trace buffer that should not wrap often) +#define FAPI_IMP(_fmt_, _args_...) FAPI_TRACE("imp", _fmt_, ##_args_) + +// Error traces (go into slow trace buffer that should not wrap often) +#define FAPI_ERR(_fmt_, _args_...) FAPI_TRACE("err", _fmt_, ##_args_) + +// Debug traces (go into fast trace buffer that can wrap often) +#define FAPI_DBG(_fmt_, _args_...) FAPI_TRACE("dbg", _fmt_, ##_args_) + +// Scan traces +#define FAPI_SCAN(_fmt_, _args_...) FAPI_TRACE("scan", _fmt_, ##_args_) + +#define FAPI_MFG(_fmt_, _args_...) FAPI_TRACE("mfg", _fmt_, ##_args_) + +#endif // FAPI2_PLATTRACE_H_ diff --git a/src/ppe/hwpf/plat/include/return_code.H b/src/ppe/hwpf/plat/include/return_code.H new file mode 100644 index 0000000..67aa0ab --- /dev/null +++ b/src/ppe/hwpf/plat/include/return_code.H @@ -0,0 +1,187 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/return_code.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file return_code.H + * @brief definitions for fapi2 return codes + */ + +#ifndef __FAPI2_RETURN_CODE__ +#define __FAPI2_RETURN_CODE__ + +#include <stdint.h> + +// Remove this for platforms which don't support FFDC +//#include <ffdc.H> + +/// +/// @brief Set HWP Error macro +/// +/// This macro should be used by a HWP to create an error. The ReturnCode's +/// internal return code is set and any error information in the Error XML file +/// is added to the ReturnCode +/// +#define FAPI_SET_HWP_ERROR(RC, ERROR) \ + RC._setHwpError(fapi2::ERROR); \ + ERROR##_CALL_FUNCS_TO_COLLECT_FFDC(RC); \ + ERROR##_CALL_FUNCS_TO_COLLECT_REG_FFDC(RC); \ + ERROR##_ADD_ERROR_INFO(RC) + +/// +/// @brief Add info to HWP Error macro +/// +/// This macro should be used by an FFDC HWP to add error information from an +/// Error XML file to an existing error. +/// +#define FAPI_ADD_INFO_TO_HWP_ERROR(RC, ERROR) \ + ERROR##_CALL_FUNCS_TO_COLLECT_FFDC(RC); \ + ERROR##_CALL_FUNCS_TO_COLLECT_REG_FFDC(RC); \ + ERROR##_ADD_ERROR_INFO(RC) + +namespace fapi2 +{ + /// + /// @brief Enumeration of return codes + /// + enum ReturnCodes + { + ///< Success + FAPI2_RC_SUCCESS = 0, + + // Flag bits indicating which code generated the error. + FAPI2_RC_FAPI2_MASK = 0x04000000, ///< FAPI2 mask + FAPI2_RC_PLAT_MASK = 0x02000000, ///< Platform mask + FAPI2_RC_HWP_MASK = 0x00000000, ///< HWP mask + + // + // FAPI generated return codes + // + + FAPI2_RC_INVALID_ATTR_GET = FAPI2_RC_FAPI2_MASK | 0x01, + ///< Initfile requested an attribute with an invalid attribute ID + + FAPI2_RC_INVALID_CHIP_EC_FEATURE_GET = FAPI2_RC_FAPI2_MASK | 0x02, + ///< HWP requested a chip EC feature with an invalid attribute ID + + FAPI2_RC_INVALID_MULTISCOM_LENGTH = FAPI2_RC_FAPI2_MASK | 0x03, + ///< Invalid multiscom parameters + + FAPI2_RC_INVALID_PARAMETER = FAPI2_RC_FAPI2_MASK | 0x04, + ///< Invalid parameters to a FAPI2 function + + FAPI2_RC_OVERFLOW = FAPI2_RC_FAPI2_MASK | 0x05, + ///< Overflow condition, typically a buffer operation + + // + // PLAT generated return codes. Additional details may be contained in + // ReturnCode platData (this can only be looked at by PLAT code) + // + + FAPI2_RC_PLAT_ERR_SEE_DATA = FAPI2_RC_PLAT_MASK | 0x01, + ///< Generic platform error + + FAPI2_RC_PLAT_ERR_ADU_LOCKED = FAPI2_RC_PLAT_MASK | 0x02, + ///< Operation to AlterDisplay unit failed because it is locked + + FAPI2_RC_PLAT_NOT_SUPPORTED_AT_RUNTIME = FAPI2_RC_PLAT_MASK | 0x03, + ///< Operation not supported by HB runtime + }; + + + /// + /// @brief Class representing a FAPI2 ReturnCode + /// + /// @note Remove the inheritance relationship with FirstFailureData if + /// the platform doesn't support FFDC. + class ReturnCode + { + public: + + /// + /// @brief Constructor. + /// @param[in] i_rc the rc to set + /// + ReturnCode(const uint32_t i_rc = FAPI2_RC_SUCCESS): + iv_rc(i_rc) + {}; + + /// + /// @brief integral type conversion function. Returns the error code + /// @return The error code + /// + inline operator uint32_t() const { return iv_rc; } + + /// + /// @brief Returns true iff iv_rc == SUCCESS + /// @return true or false + /// + inline operator bool() const { return iv_rc == FAPI2_RC_SUCCESS; } + + /// + /// @brief Assignement operator + /// + inline ReturnCode& operator=(const uint32_t& rhs) + { + iv_rc = rhs; + return *this; + } + + inline ReturnCode& operator=(const ReturnCodes& rhs) + { + iv_rc = rhs; + return *this; + } + + inline bool operator==(const uint32_t& rhs) const + { return rhs == iv_rc; } + + inline bool operator==(const ReturnCodes& rhs) const + { return rhs == iv_rc; } + + inline bool operator!=(const uint32_t& rhs) const + { return rhs != iv_rc; } + + inline bool operator!=(const ReturnCodes& rhs) const + { return rhs != iv_rc; } + + ReturnCode& insertPIBcode(const uint32_t& pibrc) + { + iv_rc = FAPI2_RC_PLAT_MASK | pibrc; + return *this; + } + + private: + uint32_t iv_rc; + }; + + /// This implementation assumes no exception handling and leverages thread-local + /// storage. For platforms without thread support, a global variable will + /// suffice for the error state. + extern thread_local ReturnCode current_err; /// the current error state + extern thread_local uint32_t pib_error_mask; /// the pib mask + extern thread_local uint32_t operational_state; /// the operational mode + +}; + +#endif diff --git a/src/ppe/hwpf/plat/include/target.H b/src/ppe/hwpf/plat/include/target.H new file mode 100644 index 0000000..c23b43e --- /dev/null +++ b/src/ppe/hwpf/plat/include/target.H @@ -0,0 +1,553 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/target.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file target.H + * @brief definitions for fapi2 targets + */ + +#ifndef __FAPI2_TARGET__ +#define __FAPI2_TARGET__ + +#include <stdint.h> +//#include <vector> +#include <target_types.H> +#include <utils.H> +#include "plat_target_parms.H" + +#define MC_ENABLE 0x1 << 6 +#define MC_WRITE 5 +#define MC_READ_OR 0 +#define MC_READ_AND 1 + +#define EX_ADDRESS_MASK 0x0000FF00 + +#ifdef __ASSEMBLER__ + +#ifndef ULL +#define ULL(x) x +#endif + +#else + +#ifndef ULL +#define ULL(x) x##ull + +#endif + +#endif // __ASSEMBLER + +/// Create a multi-bit mask of \a n bits starting at bit \a b +#define BITS(b, n) ((ULL(0xffffffffffffffff) << (64 - (n))) >> (b)) + +/// Create a single bit mask at bit \a b +#define BIT(b) BITS((b), 1) + + +namespace fapi2 +{ + /// + /// @brief Class representing a FAPI2 Target + /// @tparam K the type (Kind) of target + /// @tparam V the type of the target's Value + /// @remark TargetLite targets are uint64_t, Targets + /// are uintptr_t (void*). + /// + /// Assuming there are representations of a processor, + /// a membuf and a system here are some examples: + /// @code + /// #define PROCESSOR_CHIP_A 0xFFFF0000 + /// #define MEMBUF_CHIP_B 0x0000FFFF + /// #define SYSTEM_C 0x0000AAAA + /// @endcode + /// + /// * To define a target: + /// @code + /// fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> A(PROCESSOR_CHIP_A); + /// fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> C(SYSTEM_C); + /// fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> B(MEMBUF_CHIP_B); + /// @endcode + /// + /// * Functions which take composite target types + /// @code + /// void takesProcOrMembuf( + /// const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP | + /// fapi2::TARGET_TYPE_MEMBUF_CHIP>& V ); + /// + /// void takesAny(const fapi2::Target<fapi2::TARGET_TYPE_ALL>& V ); + /// + /// @endcode + /// + /// * Traversing the target "tree" + /// @code + /// fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> A(PROCESSOR_CHIP_A); + /// + /// // Get A's parent + /// A.getParent<fapi2::TARGET_TYPE_SYSTEM>(); + /// + /// // Get the 0x53'd core + /// fapi2::getTarget<fapi2::TARGET_TYPE_CORE>(0x53); + /// + /// // Get all *my* present/functional children which are cores + /// A.getChildren<fapi2::TARGET_TYPE_CORE>(); + /// + /// // Get all of the the cores relative to my base target + /// fapi2::getChildren<fapi2::TARGET_TYPE_CORE>(); + /// @endcode + /// + /// * Invalid casts + /// @code + /// // Can't cast to a specialized target + /// fapi2::Target<fapi2::TARGET_TYPE_NONE> D(MEMBUF_CHIP_B); + /// takesProcOrMembuf( D ); + /// + /// // Not one of the shared types + /// fapi2::Target<fapi2::TARGET_TYPE_ABUS_ENDPOINT> E; + /// takesProcOrMembuf( E ); + /// @endcode + template<TargetType K, typename V = uint64_t> + class Target + { + public: + + /// + /// @brief Create a Target, with a value + /// @param[in] V the value (i.e., specific element this + /// target represents, or pointer) + /// @note Platforms can mangle the value and K to get a + /// single uint64_t in value which represents all the information + /// they might need. value( K | V ), for example + /// + + /// Default constructor is basically a TARGET_TYPE_ALL + Target() + { + this->iv_handle.fields.chiplet_num = 0; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + + Target( V Value ) + { + static_assert( ((K == TARGET_TYPE_CORE) & + (K == TARGET_TYPE_EQ) ) != true, + "TARGET_TYPE_CORE and TARGET_TYPE_EQ cannot be specified at the same time"); + + if(K & TARGET_TYPE_PROC_CHIP) + { + this->iv_handle.fields.chiplet_num = Value; + this->iv_handle.fields.type = TARGET_TYPE_PROC_CHIP; + this->iv_handle.fields.type_target_num = Value; // TODO: check this +// this->iv_address.fields.chiplet_num = Value; + } + + if(K & TARGET_TYPE_PERV) + { + this->iv_handle.fields.chiplet_num = Value; + this->iv_handle.fields.type = TARGET_TYPE_PERV | TARGET_TYPE_PROC_CHIP; + this->iv_handle.fields.type_target_num = Value; // TODO: check this +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + + if(K & TARGET_TYPE_CORE) + { + /* + if (Value > CORE_CHIPLET_COUNT) + { + PK_TRACE("Chiplet number is greater than CORE_CHIPLET_COUNT"); + return -1; + } + */ + this->iv_handle.fields.chiplet_num = Value + CORE_CHIPLET_OFFSET; + this->iv_handle.fields.type = TARGET_TYPE_CORE; + this->iv_handle.fields.type_target_num = Value; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + + if(K & TARGET_TYPE_EQ) + { + this->iv_handle.fields.chiplet_num = Value + EQ_CHIPLET_OFFSET; + this->iv_handle.fields.type = TARGET_TYPE_EQ; + this->iv_handle.fields.type_target_num = Value; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + + if(K & TARGET_TYPE_EX) + { + + this->iv_handle.fields.chiplet_num = (Value / 2) + EX_CHIPLET_OFFSET; + this->iv_handle.fields.type = TARGET_TYPE_EX; + this->iv_handle.fields.type_target_num = Value; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + + if(K & TARGET_TYPE_EQ_MC_WRITE) + { + this->iv_handle.fields.chiplet_num = + (((MC_ENABLE) | + ((MC_WRITE << 3) | (Value & 0x07))) & + BITS(57,7)); + this->iv_handle.fields.type = TARGET_TYPE_EQ_MC_WRITE; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + + if(K & TARGET_TYPE_EQ_MC_READOR) + { + this->iv_handle.fields.chiplet_num = + (((MC_ENABLE) | + ((MC_READ_OR << 3) | (Value & 0x07))) & + BITS(57,7)); + this->iv_handle.fields.type = TARGET_TYPE_EQ_MC_READOR; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + + if(K & TARGET_TYPE_EQ_MC_READAND) + { + this->iv_handle.fields.chiplet_num = + (((MC_ENABLE) | + ((MC_READ_AND << 3) | (Value & 0x07))) & + BITS(57,7)); + this->iv_handle.fields.type = TARGET_TYPE_EQ_MC_READAND; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + + if(K & TARGET_TYPE_CORE_MC_WRITE) + { + this->iv_handle.fields.chiplet_num = + (((MC_ENABLE) | + ((MC_WRITE << 3) | (Value & 0x07))) & + BITS(57,7)); + this->iv_handle.fields.type = TARGET_TYPE_CORE_MC_WRITE; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + + if(K & TARGET_TYPE_CORE_MC_READOR) + { + this->iv_handle.fields.chiplet_num = + (((MC_ENABLE) | + ((MC_READ_OR << 3) | (Value & 0x07))) & + BITS(57,7)); + this->iv_handle.fields.type = TARGET_TYPE_CORE_MC_READOR; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + + if(K & TARGET_TYPE_CORE_MC_READAND) + { + this->iv_handle.fields.chiplet_num = + (((MC_ENABLE) | + ((MC_READ_AND << 3) | (Value & 0x07))) & + BITS(57,7)); + this->iv_handle.fields.type = TARGET_TYPE_CORE_MC_READAND; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + + if(K == TARGET_TYPE_ALL) + { + this->iv_handle.fields.chiplet_num = Value; + this->iv_handle.fields.type = TARGET_TYPE_ALL; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + } + +// if(K == TARGET_TYPE_ADDRESS) +// { +// this->iv_handle.fields.chiplet_num = Value; +// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; +// } + } + + /// + /// @brief Assignment Operator. + /// @param[in] i_right Reference to Target to assign from. + /// @return Reference to 'this' Target + /// + Target<K,V>& operator=(const Target<K,V>& i_right) + { + this->iv_handle.value = i_right->iv_handle.value; + this->iv_addresss.value = i_right->iv_address.value; + return *this; + } + + /// + /// @brief Equality Comparison Operator + /// @param[in] i_right Reference to Target to compare. + /// @return bool. True if equal. + /// + bool operator==(const Target<K,V>& i_right) const + { + if (this->iv_handle.value == i_right->iv_handle.value) + return true; + else + return false; + } + /// + /// @brief Inquality Comparison Operator + /// @param[in] i_right Reference to Target to compare. + /// @return bool. True if equal. + /// + bool operator!=(const Target<K,V>& i_right) const + { + if (this->iv_handle.value != i_right->iv_handle.value) + return true; + else + return false; + } + + /// + /// @brief Get the handle. + /// @return V The target's handle, or value + /// + V get(void) const + { + return this->iv_handle.value; + } + + /// + /// @brief Get the handle as a V + /// @return V The target's handle, or value + /// + operator V() const + { + return this->iv_handle.value; + } + + /// + /// @brief Get a target's value + /// @return V The target's handle, or value + /// + V& operator()(void) + { + return *this->iv_handle; + } + + /// + /// @brief Get the target type + /// @return The type of target represented by this target + /// + TargetType getType(void) const + { + return (TargetType)this->iv_handle.fields.type; + } + + /// + /// @brief Get address overlay to reduce runtime processing + /// @return Overlay as a type V + /// + V getAddressOverlay(void) const + { + return this->iv_handle.fields.address_overlay; + } + + +#if 0 + /// + /// @brief Get this target's immediate parent + /// @tparam T The type of the parent + /// @return Target<T> a target representing the parent + /// + template<TargetType T> + Target<T,V> getParent(void) const + { + static_assert((T & ~(TARGET_TYPE_PROC_CHIP | TARGET_TYPE_PERV) != 0), + "Only TARGET_TYPE_PROC_CHIP and TARGET_TYPE_PERV parent types supported"); + + static_assert( ((((T & TARGET_TYPE_PROC_CHIP) == 0) & + (T & TARGET_TYPE_PERV ) == 0) ), + "Either TARGET_TYPE_PROC_CHIP or TARGET_TYPE_PERV parent type must be specified"); + } + + /// + /// @brief Get this target's children + /// @tparam T The type of the parent + /// @return std::vector<Target<T> > a vector of present/functional + /// children + /// + template< TargetType T> + std::vector<Target<T,V> > getChildren(void) const + { + static_assert( ((T & ~TARGET_TYPE_PROC_CHIP) != 0 ) != true, + "Only TARGET_TYPE_CHIP and TARGET_TYPE_EQ child types supported"); + + if(K & TARGET_TYPE_PROC_CHIP) + { + std::vector<Target<T,V> chip_children(CHIPLET_COUNT); + for (int i = 0; i < CHIPLET_COUNT; i++) + { + if (this->iv_handle.fields.type == TARGET_TYPE_PROC_CHIP & + this->iv_handle.fields.present = 1 & + this->iv_handle.fields.functional = 1 ) + { + chip_children.push_back(this->iv_handle) + } + } + return chip_children; + } + + if(K & TARGET_TYPE_PERV) + { + this->iv_handle.fields.chiplet_num = Value; + // this->iv_handle.fields.type_perv = 1; + this->iv_handle.fields.type_target_num = 0; + } + + } + + /// + /// @brief Get the target at the other end of a bus - dimm included + /// @tparam T The type of the parent + /// @return Target<T> a target representing the thing on the other end + /// @note Can be easily changed to a vector if needed + /// + template<TargetType T> + Target<T,K> getOtherEnd(void) const + { + static_assert( false, "getOtherEnd() is not supported on PPE platforms"); + } +#endif + + /// + /// @brief Copy from a Target<O> to a Target<K> + /// @tparam O the target type of the other + /// + template<TargetType O> + Target<K,V>( const Target<O>& Other ): + Target<K,V>(Other.get()) + { + static_assert( (K & O) != 0, + "unable to cast Target, no shared types"); + + static_assert( bitCount<K>::count >= bitCount<O>::count, + "unable to cast to specialized Target"); + } + + private: + +// union { +// V value; +// struct { +// #ifdef _BIG_ENDIAN +// V chiplet_num : 8; +// V _reserved_b24 : 24; +// #else +// V _reserved_b24 : 24; +// V chiplet_num : 8; +// #endif +// } fields; +// +// } iv_address; +// + union { + V value; + struct { +#ifdef _BIG_ENDIAN + V chiplet_num : 8; + V type_target_num : 8; + V type : 8; + V _reserved_b6 : 6; + V present : 1; + V functional : 1; + V address_overlay : 32; +#else + V address_overlay : 32; + V functional : 1; + V present : 1; + V _reserved_b6 : 6; + V type : 8; + V type_target_num : 8; + V chiplet_num : 8; +#endif + } fields; + } iv_handle ; + +// uint64_t iv_present_children; +// uint64_t iv_functional_children; + + }; + + +#if 0 + /// + /// @brief Return the string interpretation of this target + /// @tparam T The type of the target + /// @tparam B The type of the buffer + /// @param[in] The Target<T> + /// @param[in] The buffer + /// @return void + /// @post The contents of the buffer is replaced with the string + /// representation of the target + /// + template<TargetType T, typename B> + void toString(const Target<T>& i_target, B& i_buffer) + { + static_assert( false, "toString is not supported on PPE platforms"); + } + + /// + /// @brief Get an enumerated target of a specific type + /// @tparam T The type of the target + /// @param[in] uint64_t representing the ordinal number of + /// the desired target + /// @return Target<T> the target requested + /// + template<TargetType T> + Target<T> getTarget(uint64_t Ordinal) + { + // For testing + return Target<T>(Ordinal); + } +#endif + // Why has the been removed? For starters, the API name + // is probably wrong as it's already been confused with + // Target::getChildren(). And if I'm going to change it + // I really want to see if we need it. I'm still not + // clear on whether we're alloing this traversal or not. +#if 0 + /// + /// @brief Get the base target's children + /// @tparam T The type of the target + /// @return std::vector<Target<T> > a vector of present/functional + /// children + /// + template<TargetType T> + std::vector<Target<T> > getChildren() + { + // For testing + return {Target<T>(), Target<T>()}; + } +#endif + + /// + /// @brief Check if the target is of a type, or in a type subset. + /// @tparam K the TargetType to check + /// @tparam T TargetType or TargetType composite to check against + /// @return True, iff K is a proper T + /// + template< TargetType K, TargetType T > + constexpr bool is_same(void) + { return (K & T) != 0; } + + + + +}; +//#include "plat_ppe_targets_hold.H" +#endif diff --git a/src/ppe/hwpf/plat/include/target_types.H b/src/ppe/hwpf/plat/include/target_types.H new file mode 100644 index 0000000..11c48ed --- /dev/null +++ b/src/ppe/hwpf/plat/include/target_types.H @@ -0,0 +1,132 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/target_types.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file target_types.H + * @brief definitions for fapi2 target types + */ + +#ifndef __FAPI2_TARGET_TYPES__ +#define __FAPI2_TARGET_TYPES__ + +#ifndef __ASSEMBLER__ + + +/// FAPI namespace +namespace fapi2 +{ + /// + /// @enum fapi::TargetType + /// @brief Types, kinds, of targets + /// @note TYPE_NONE is used to represent empty/NULL targets in lists + /// or tables. TYPE_ALL is used to pass targets to methods which + /// can act generally on any type of target + /// + /// Target Kind + enum TargetType + { + TARGET_TYPE_NONE = 0x00, ///< No type + TARGET_TYPE_PROC_CHIP = 0x01, ///< Processor type + TARGET_TYPE_EX = 0x02, ///< Ex type + TARGET_TYPE_CORE = 0x04, ///< Core type + TARGET_TYPE_EQ = 0x08, ///< EQ type + TARGET_TYPE_PERV = 0x10, ///< Pervasive type + TARGET_TYPE_EQ_MC_WRITE = 0x20, ///< EQ Multicast Type + TARGET_TYPE_EQ_MC_READAND = 0x21, ///< EQ Multicast Read AND Type + TARGET_TYPE_EQ_MC_READOR = 0x22, ///< EQ Multicast Read OR Type + TARGET_TYPE_CORE_MC_WRITE = 0x23, ///< Core Multicast Type + TARGET_TYPE_CORE_MC_READAND = 0x24, ///< Core Multicast Read AND Type + TARGET_TYPE_CORE_MC_READOR = 0x25, ///< Core Multicast Read OR Type + TARGET_TYPE_CME_CORE0 = 0x40, ///< CME Core0 (CME only) + TARGET_TYPE_CME_CORE1 = 0x41, ///< CME Core1 (CME only) + TARGET_TYPE_ALL = 0xFF, ///< Any/All types + + +// TARGET_TYPE_NONE = 0x00000000, ///< No type +// TARGET_TYPE_SYSTEM = 0x00000001, ///< System type +// TARGET_TYPE_DIMM = 0x00000002, ///< DIMM type +// TARGET_TYPE_PROC_CHIP = 0x00000004, ///< Processor type +// TARGET_TYPE_MEMBUF_CHIP = 0x00000008, ///< Membuf type +// TARGET_TYPE_EX = 0x00000010, ///< Ex type +// TARGET_TYPE_MBA = 0x00000020, ///< MBA type +// TARGET_TYPE_MCS = 0x00000040, ///< MCS type +// TARGET_TYPE_XBUS = 0x00000080, ///< XBUS type +// TARGET_TYPE_ABUS = 0x00000100, ///< ABUS type +// TARGET_TYPE_L4 = 0x00000200, ///< L4 type +// TARGET_TYPE_CORE = 0x00000400, ///< Core type +// TARGET_TYPE_EQ = 0x00000800, ///< EQ type +// TARGET_TYPE_MCA = 0x00001000, ///< MCA type +// TARGET_TYPE_MCBIST = 0x00002000, ///< MCBIST type +// TARGET_TYPE_MIA = 0x00004000, ///< MIA type +// TARGET_TYPE_MIS = 0x00008000, ///< MIS type +// TARGET_TYPE_DMI = 0x00010000, ///< DMI type +// TARGET_TYPE_OBUS = 0x00020000, ///< OBUS type +// TARGET_TYPE_NV = 0x00040000, ///< NV bus type +// TARGET_TYPE_SBE = 0x00080000, ///< SBE type +// TARGET_TYPE_PPE = 0x00100000, ///< PPE type +// TARGET_TYPE_PERV = 0x00200000, ///< Pervasive type +// TARGET_TYPE_PEC = 0x00400000, ///< PEC type +// TARGET_TYPE_PHB = 0x00800000, ///< PHB type +// TARGET_TYPE_EQ_MC_WRITE = 0x01000000, ///< EQ Multicast Type +// TARGET_TYPE_EQ_MC_READAND = 0x02000000, ///< EQ Multicast Read AND Type +// TARGET_TYPE_EQ_MC_READOR = 0x04000000, ///< EQ Multicast Read OR Type +// TARGET_TYPE_CORE_MC_WRITE = 0x08000000, ///< Core Multicast Type +// TARGET_TYPE_CORE_MC_READAND = 0x10000000, ///< Core Multicast Read AND Type +// TARGET_TYPE_CORE_MC_READOR = 0x20000000, ///< Core Multicast Read OR Type +// TARGET_TYPE_CME_CORE0 = 0x40000000, ///< CME Core0 (CME only) +// TARGET_TYPE_CME_CORE1 = 0x80000000, ///< CME Core1 (CME only) +// TARGET_TYPE_ADDRESS = 0xAAAAAAAA, ///< Address Overlay Type +// TARGET_TYPE_ALL = 0xFFFFFFFF, ///< Any/All types + }; + + + /** + * @brief Typedef used when passing multiple TargetType values + */ + typedef uint8_t TargetTypes_t; + + /// @cond + constexpr TargetType operator|(TargetType x, TargetType y) + { + return static_cast<TargetType>(static_cast<int>(x) | + static_cast<int>(y)); + } + + template<uint64_t V> + class bitCount { + public: + // Don't use enums, too hard to compare + static const uint8_t count = bitCount<(V >> 1)>::count + (V & 1); + }; + + template<> + class bitCount<0> { + public: + static const uint8_t count = 0; + }; + /// @endcond +}; + +#endif // __ASSEMBLER__ +#endif // __FAPI2_TARGET_TYPES__ diff --git a/src/ppe/hwpf/plat/include/utils.H b/src/ppe/hwpf/plat/include/utils.H new file mode 100644 index 0000000..8fb74cb --- /dev/null +++ b/src/ppe/hwpf/plat/include/utils.H @@ -0,0 +1,56 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/utils.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file utils.H + * + * @brief Defines common utility elements for FAPI2 use. + */ + +#ifndef FAPI2_UTILS_H_ +#define FAPI2_UTILS_H_ + +#ifdef __ASSEMBLER__ + +#ifndef ULL +#define ULL(x) x +#endif + +#else + +#ifndef ULL +#define ULL(x) x##ull + +#endif + +#endif // __ASSEMBLER + +/// Create a multi-bit mask of \a n bits starting at bit \a b +#define BITS(b, n) ((ULL(0xffffffffffffffff) << (64 - (n))) >> (b)) + +/// Create a single bit mask at bit \a b +#define BIT(b) BITS((b), 1) + + +#endif // FAPI2_UTILS_H_ diff --git a/src/ppe/hwpf/plat/include/variable_buffer.H b/src/ppe/hwpf/plat/include/variable_buffer.H new file mode 100644 index 0000000..55f0577 --- /dev/null +++ b/src/ppe/hwpf/plat/include/variable_buffer.H @@ -0,0 +1,670 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/include/variable_buffer.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file variable_buffer.H + * @brief definitions for fapi2 variable length buffers + */ + +#ifndef __FAPI2_VARIABLE_BUFFER__ +#define __FAPI2_VARIABLE_BUFFER__ + +#include <buffer_base.H> + +namespace fapi2 +{ + /// @brief Get a 32 bit mask quickly + // This is one of the main reasons we static_assert in the ctor's + // to ensure the unit_type is 32 bits. + inline uint32_t fast_mask32(int32_t i_pos, int32_t i_len) + { + // generates an arbitrary 32-bit mask using two operations, not too shabby + + static const uint32_t l_mask32[] = { + 0x00000000, + 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000, + 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000, + 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, + 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000, + 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, + 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, + 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0, + 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF, + }; + return l_mask32[i_len] >> i_pos; + } + + // + // General set a series of bits in the buffer. + // + + /// + /// @cond + /// @brief Internal bit inserting method. + /// @tparam unit_type The type of a unit of the arrays + /// @tparam bits_type The type of the bit counting values + /// @param[in] i_source The incoming data + /// @param[in] i_source_length The length in bits of the incoming data + /// @param[in] i_target The outgoing data + /// @param[in] i_target_length The length in bits of the outgoing data + /// @param[in] i_source_start_bit The starting bit location in the + /// incoming data + /// @param[in] i_target_start_bit The starting bit position in this + /// @param[in] i_length The length, in bits, the user wants copied. + /// + template<typename unit_type, typename bits_type> + inline fapi2::ReturnCode _insert(const unit_type* i_source, + bits_type i_source_length, + unit_type* i_target, + bits_type i_target_length, + bits_type i_source_start_bit, + bits_type i_target_start_bit, + bits_type i_length) + { + const bits_type bits_per_unit = fapi2::parameterTraits<unit_type>::bit_length; + + // tartgetStart is defaulted to the sizeof(target) - (sizeof(source) - i_source_start_bit) + // which makes this act like insert from right + if (i_target_start_bit == ~0) + { + i_target_start_bit = (i_target_length - (i_source_length - i_source_start_bit)); + } + + // len defaults to (sizeof(OT) * 8) - i_source_start_bit + if (i_length == ~0) + { + i_length = i_source_length - i_source_start_bit; + } + + // Check for overflow + if ((i_length + i_target_start_bit > i_target_length) || + (i_length + i_source_start_bit > i_source_length)) + { + return fapi2::FAPI2_RC_OVERFLOW; + } + + do + { + const bits_type src_idx = i_source_start_bit / bits_per_unit; + const bits_type trg_idx = i_target_start_bit / bits_per_unit; + + // "slop" = unaligned bits + const bits_type src_slop = i_source_start_bit % bits_per_unit; + const bits_type trg_slop = i_target_start_bit % bits_per_unit; + + // "cnt" = largest number of bits to be moved each pass + bits_type cnt = std::min(i_length, bits_per_unit); + cnt = std::min(cnt, bits_per_unit - src_slop); + cnt = std::min(cnt, bits_per_unit - trg_slop); + + // generate the source mask only once + bits_type mask = fast_mask32(src_slop, cnt); + + // read the source bits only once + bits_type src_bits = i_source[src_idx] & mask; + + // "shift" = amount of shifting needed for target alignment + int32_t shift = trg_slop - src_slop; + + // ideally (i << -1) would yield (i >> 1), but it + // doesn't, so we need an extra branch here + + if (shift < 0) + { + src_bits <<= -shift; + mask <<= -shift; + } + else + { + src_bits >>= shift; + mask >>= shift; + } + + // clear source '0' bits in the target + i_target[trg_idx] &= ~mask; + // set source '1' bits in the target + i_target[trg_idx] |= src_bits; + + i_source_start_bit += cnt; + i_target_start_bit += cnt; + + i_length -= cnt; + } while (0 < i_length); + + return fapi2::FAPI2_RC_SUCCESS; + } + /// @endcond + + /// @brief Class representing a FAPI variable_buffer. + /// @remark Variable buffers are buffers which can be variable in length + /// (and "odd sized.") These best represent the FAPI 1.X ecmdDataBuffer, + /// however they are implemented using the same template techniques + /// as the new fapi::buffer. + /// @note Variable buffers are not (presently) declared as std::bitset + /// as bitsets' size is fixed at runtime. It is not clear if this is + /// acceptable for variable_buffers at this time. + /// @note Variable buffers are not (presently) declared as std::vector<bool> + /// as it would need to be implemented separate from std::vector, and + /// it's not clear it would give us any real advantage. Howevever, its is + /// more likely this will become a std::vector<bool> than a std::bitset. + class variable_buffer : public buffer_base<bits_container> + { + + public: + + /// + /// @brief Variable buffer constructor + /// @param[in] i_value number of *bits* (sizeof(uint_type) * 8) + /// needed. + variable_buffer(bits_type i_value = 0); + + /// + /// @brief Variable buffer list constructor + /// @param[in] i_value an initializer list to initialize the container. + /// + variable_buffer(const std::initializer_list<unit_type>& i_value); + + /// @name Bit/Word Manipulation Functions + ///@{ + + /// + /// @brief Return the length of the buffer in bits + /// @return Length in bits + /// + inline uint32_t getBitLength(void) const + { return iv_perceived_bit_length; } + + /// + /// @brief Return the length of the buffer in OT units + /// @return Length in OT units rounded up + /// @tparam OT the type to get the length of. For example, if one + /// wanted the length in double words, OT would be uint64_t + /// (getLength<uint64_t>().) Similarly, to get the length in words, + /// getLength<uin32_t>(). + /// + template< typename OT > + inline uint32_t getLength(void) const + { + static const uint32_t bits_in_ot = sizeof(OT) * 8; + return (getBitLength() + (bits_in_ot - 1)) / bits_in_ot; + } + + /// + /// @brief Set a bit in the buffer + /// @param[in] i_bit the bit number to set. + /// @note 0 is left-most + /// @return FAPI2_RC_SUCCESS if OK + /// + inline fapi2::ReturnCode setBit(const bits_type& i_bit) + { + const bits_type index = i_bit / bits_per_unit; + + if (index > iv_data.size()) + { + return FAPI2_RC_INVALID_PARAMETER; + } + + +/// @todo: check with Brian no the correct parens + iv_data[index] |= + unit_type(1) << ((bits_per_unit - 1) - + (i_bit - (index * bits_per_unit))); + + return FAPI2_RC_SUCCESS; + } + + /// + /// @brief Clear a bit in buffer + /// @tparam SB Start bit in buffer to clear. + /// @tparam L Number of consecutive bits from start bit to + /// clear + /// @return FAPI2_RC_SUCCESS on success + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template< bits_type SB, bits_type L > + fapi2::ReturnCode clearBit(void); + + /// + /// @brief Invert bit + /// @tparam SB Start bit in buffer to invert. + /// @tparam L Number of consecutive bits from start bit to + /// invert, defaults to 1 + /// @return FAPI2_RC_SUCCESS on success + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template< bits_type SB, bits_type L = 1 > + fapi2::ReturnCode flipBit(void); + + /// + /// @brief Get the value of a bit in the buffer + /// @tparam B Bit in buffer to get. + /// @return true/1 if bit is on, false/0 if bit is off + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// + template< bits_type B > + inline bool getBit(void) const + { + const bits_type index = B / bits_per_unit; + const unit_type mask = unit_type(1) << (bits_per_unit - 1) - (B - (index * bits_per_unit)); + return iv_data[index] & mask; + } + + /// + /// @brief Test if multiple bits are set + /// @tparam SB Start bit in buffer to test. + /// @tparam L Number of consecutive bits from start bit to + /// test, defaults to 1 + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// @return true if all bits in range are set - false if any + /// bit is clear + /// + template< bits_type SB, bits_type L = 1 > + bool isBitSet(void) const; + + /// + /// @brief Test if multiple bits are clear + /// @tparam SB Start bit in buffer to test. + /// @tparam L Number of consecutive bits from start bit to + /// test, defaults to 1 + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// @return true if bit is clear - false if bit is set + /// + template< bits_type SB, bits_type L = 1 > + bool isBitClear(void) const; + + /// + /// @brief Count number of bits set in a range + /// @tparam SB Start bit in buffer to test. + /// @tparam L Number of consecutive bits from start bit to + /// test, defaults to 1 + /// @note Asserting that all the parameters are known at + /// compile time so this can be templated only. If that is not + /// the case we can add a function parameter version. + /// @return Number of bits set in range + /// + template< bits_type SB, bits_type L = 1 > + bits_type getNumBitsSet(void) const; + + ///@} + + /// @name Buffer Manipulation Functions + ///@{ + + // Note: Many (all?) of these are not needed and the compiler complains + // as the cast to T yields a better operator. There are here mainly for + // documenation purposes. + + /// + /// @brief operator>>() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator>>(bits_type i_shiftnum); +#endif + + /// + /// @brief operator<<() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator<<(bits_type i_shiftnum); +#endif + + /// + /// @brief operator+() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator+(const T& rhs); +#endif + + /// + /// @brief operator+=() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator+=(const T& rhs); +#endif + + /// + /// @brief operator|=() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator|=(const T& rhs); +#endif + + /// + /// @brief operator&=() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator&=(const T& rhs); +#endif + + /// + /// @brief operator|() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator|(const T& rhs); +#endif + + /// + /// @brief operator&() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator&(const T& rhs); +#endif + + /// + /// @brief operator^=() + /// +#ifdef DOXYGEN + variable_buffer<T>& operator^=(const T& rhs); +#endif + + /// + /// @brief operator!=() + /// +#ifdef DOXYGEN + bool operator!=(const T& rhs) const; +#endif + + /// + /// @brief operator==() + /// @return true if and only if lhs == rhs + /// + inline bool operator==(const fapi2::bits_container& rhs) const + { + if (&iv_data == &rhs) + { + return true; + } + + return iv_data == rhs; + } + + /// + /// @brief Copy part of an element into the DataBuffer + /// @param[in] i_data OT value to copy into DataBuffer + /// @param[in] i_targetStart The position in this where the copy starts + /// @param[in] i_len How many bits to copy + /// @param[in] i_sourceStart The start positon in i_data, defaults to 0 + /// @return FAPI2_RC_SUCCESS on success, FAPi2_RC_OVERFLOW otherwise + /// + template<typename OT> + fapi2::ReturnCode insert(const OT& i_data, + bits_type i_targetStart = 0, + bits_type i_len = ~0, + bits_type i_sourceStart = 0); + + /// + /// @brief Copy in a right aligned (decimal) element + /// @param[in] i_data the incoming data + /// - data is taken right aligned + /// @param[in] i_targetStart The starting bit position in this + /// - Defaultst to 0 + /// @param[in] i_len The length, in bits, the user wants copied. + /// - Defaults to all of the bits in the source which fit + /// @return FAPI2_RC_SUCCESS on success, FAPI2_RC_OVERFLOW otherwise + /// + template<typename OT> + fapi2::ReturnCode insertFromRight(const OT& i_data, + bits_type i_targetStart = 0, + bits_type i_len = ~0); + + /// + /// @brief Copy data from this buffer into an OT + /// @tparam OT the type of the outgoing data + /// @param[out] o_out OT to copy into - data is placed left aligned + /// @param[in] i_start Start bit to copy from - defaults to 0 + /// @param[in] i_len Length of bits to copy - defaults to filling o_out + /// @return FAPI2_RC_SUCCESS on success + /// + template< typename OT > + fapi2::ReturnCode extract(OT& o_out, + bits_type i_start = 0, + bits_type i_len = ~0) const; + + /// + /// @brief Copy data from this buffer into an OT and right justify + /// @tparam OT the type of the outgoing data + /// @param[out] o_out OT to copy into - data is placed right aligned + /// @param[in] i_start Start bit to copy from - defaults to 0 + /// @param[in] i_len Length of bits to copy - defaults to filling o_out + /// @return FAPI2_RC_SUCCESS on success + /// + template< typename OT > + fapi2::ReturnCode extractToRight(OT& o_out, + bits_type i_start = 0, + bits_type i_len = ~0) const; + ///@} + + private: + // Just shorthand ... + static const bits_type bits_per_unit = + bufferTraits<bits_container>::bits_per_unit; + + // The number of bits the user asked for. The actual size of the + // container might be larger. + bits_type iv_perceived_bit_length; + + /// + /// @brief Internal bit extraction method. + /// @tparam OT The type of the destination + /// @param[in] i_start The starting bit position in this + /// @param[in] i_count The length, in bits, the user wants copied. + /// @param[out] o_dest Where to put the data + /// + template< typename OT > + fapi2::ReturnCode _extract(bits_type i_start, + bits_type i_count, + OT* o_dest) const; + + /// + /// @brief Internal insertFromRight + /// @param[in] i_data, the incoming data + /// @param[in] i_data_length The length in bits of the incoming data + /// @param[in] i_target_start_bit The starting bit position in this + /// @param[in] i_length The length, in bits, the user wants copied. + /// + template<typename OT> + fapi2::ReturnCode _insertFromRight(const OT& i_data, + bits_type i_data_length, + bits_type i_targetStart, + bits_type i_len); + + }; + + inline variable_buffer:: + variable_buffer(bits_type i_value): + buffer_base(i_value), + iv_perceived_bit_length(i_value) + { + static_assert(std::is_same<unit_type, uint32_t>::value, + "code currently needs unit_type to be a unit32_t"); + } + + inline variable_buffer:: + variable_buffer(const std::initializer_list<unit_type>& i_value): + buffer_base(i_value), + iv_perceived_bit_length(i_value.size() * sizeof(unit_type) * 8) + { + static_assert(std::is_same<unit_type, uint32_t>::value, + "code currently needs unit_type to be a unit32_t"); + } + + + + /// @cond + // + // Generic insert + // + template<typename OT> + inline fapi2::ReturnCode variable_buffer::insert(const OT& i_source, + bits_type i_targetStart, + bits_type i_len, + bits_type i_sourceStart) + { + return _insert((unit_type*)(&i_source), parameterTraits<OT>::bit_length, + &(iv_data[0]), getBitLength(), + i_sourceStart, i_targetStart, i_len); + } + + // + // Insert another variable_bufer + // + template<> + inline fapi2::ReturnCode variable_buffer::insert( + const variable_buffer& i_data, + bits_type i_targetStart, + bits_type i_len, + bits_type i_sourceStart) + { + return _insert((unit_type*)&(i_data()[0]), i_data.getBitLength(), + &(iv_data[0]), getBitLength(), + i_sourceStart, i_targetStart, i_len); + } + + // + // Generic insert from right + // + template<typename OT> + inline fapi2::ReturnCode variable_buffer::insertFromRight( + const OT& i_data, + bits_type i_targetStart, + bits_type i_len) + { + /// @todo check with Brian on additional return + return _insertFromRight(i_data, parameterTraits<OT>::bit_length, i_targetStart, i_len); + } + + // + // variable_buffer insert from right + // + template<> + inline fapi2::ReturnCode variable_buffer::insertFromRight( + const variable_buffer& i_data, + bits_type i_targetStart, + bits_type i_len) + { + const bits_type bit_length_of_source = i_data.getBitLength(); + /// @todo check with Brian on additional return + return _insertFromRight(i_data, bit_length_of_source, i_targetStart, i_len); + } + + + + + // + // Generic extract. Extract is an insert with the arguments reversed. + // + template<typename OT> + inline fapi2::ReturnCode variable_buffer::extract( + OT& i_data, + bits_type i_start, + bits_type i_len) const + { + // Needed to trick the compiler into matching the template below + const bits_type max_length = parameterTraits<OT>::bit_length; + + // If thy didn't pass an i_len, assume they want all the data + // which will fit. + if (i_len == ~0) + { + i_len = max_length; + } + + return _insert((container_unit*)&iv_data[0], getBitLength(), + &i_data, max_length, + i_start, 0U, i_len); + } + + // + // Extract in to another variable_bufer + // + template<> + inline fapi2::ReturnCode variable_buffer::extract( + variable_buffer& i_data, + bits_type i_start, + bits_type i_len) const + { + // If thy didn't pass an i_len, assume they want all the data + // which will fit. + // @todo Needed to add (bits_type) to compile. Not clear why this is + // different than other similar comparisons + // error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] + if ( i_len == ~(bits_type)0 ) + { + i_len = i_data.getBitLength(); + } + return _insert((container_unit*)&iv_data[0], getBitLength(), + &(i_data()[0]), i_data.getBitLength(), + i_start, 0U, i_len); + } + + + + template<typename OT> + inline fapi2::ReturnCode variable_buffer::_insertFromRight( + const OT& i_data, + bits_type i_data_length, + bits_type i_targetStart, + bits_type i_len) + { + // If they didn't pass in a length, assume they want all the i_data + // which will fit. + if( i_len == ~0 ) + { + // The longest the length can be is the length of the data + // This is the miniumum of the length of the data or the + // number of available bits + i_len = std::min(i_data_length, getBitLength() - i_targetStart); + } + + // Source start is the length, counted from the right + return insert(i_data, i_targetStart, i_len, i_data_length - i_len); + } + + // + // Invalid specializations of set + // + /// @cond + // Sepcialize the variable_buffer version to to "undefined" so the + // linker complains loudly if anyone calls it. +#if 0 + template<> + inline fapi2::ReturnCode buffer_base::set( + const variable_buffer& i_value, + bits_type i_offset); +#endif + /// @endcond +}; + + +#endif diff --git a/src/ppe/hwpf/plat/src/Makefile b/src/ppe/hwpf/plat/src/Makefile new file mode 100644 index 0000000..926aabc --- /dev/null +++ b/src/ppe/hwpf/plat/src/Makefile @@ -0,0 +1,45 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/hwpf/plat/src/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# This Makefile is designed to be invoked with the -I argument set to +# the location of the "pk.mk" for the build + +include img_defs.mk +include fapi2ppefiles.mk + + +OBJS := $(addprefix $(OBJDIR)/, $(FAPI2LIB_OBJECTS)) + +all: $(OBJS) + + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif + diff --git a/src/ppe/hwpf/plat/src/array.C b/src/ppe/hwpf/plat/src/array.C new file mode 100644 index 0000000..7bb142b --- /dev/null +++ b/src/ppe/hwpf/plat/src/array.C @@ -0,0 +1,145 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/src/array.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ +/** + * @file array.C + * @brief fapi2 arrays + */ + +#include <stdint.h> +#include <array.H> + +namespace fapi2 +{ + /// @brief Create an array + array::array(const uint32_t i_size, element_type* i_data): + iv_size(i_size), + iv_data(i_data) + { +#ifdef GREG + assert(iv_size <= size_limit); + if (iv_data == nullptr) + { + iv_data = new element_type[iv_size](); + iv_size |= delete_bit; + } +#endif + // If the caller passed in a pointer, leave it be. Don't + // initialize it or anything. That will allow a placement + // operation where generic memory can use fapi2::array + // methods without much overhead. + } + + /// @brief Destroy an array + array::~array(void) + { + if ((iv_size & delete_bit) != 0) + { +#ifdef GREG + delete[] iv_data; +#endif + } + } + + /// @brief operator[] + array::element_type& array::operator[](const uint32_t i_index) + { +#ifdef GREG + assert(i_index < size()); +#endif + return iv_data[i_index]; + } + + /// @brief operator=() + array& array::operator=(const array& i_other) + { +#ifdef GREG + // Check to make sure it'll fit. + assert(i_other.size() <= size()); +#endif + // Our new size will be the other's size. + // Save of whether we should delete our iv_data ... + uint64_t l_our_delete_state = iv_size | delete_bit; + + // ... our new size is the size (minus the delete state) of i_other + iv_size = i_other.size(); + + // ... do the copy ... +#ifdef GREG + memcpy(iv_data, i_other.iv_data, iv_size * sizeof(element_type)); +#else + for(size_t i = 0; i < iv_size * sizeof(element_type); ++i) + { + iv_data[i] = i_other.iv_data[i]; + } +#endif + + // ... and record our old delete state. + iv_size |= l_our_delete_state; + + return *this; + } + + /// @brief move operator=() + array& array::operator=(array&& i_other) + { + iv_size = i_other.iv_size; + + // Make sure to clear the delete bit in the other. We + // don't want our memory to be deleted. + i_other.iv_size = i_other.size(); + + iv_data = std::move(i_other.iv_data); + return *this; + } + + /// @brief operator==() + bool array::operator==(const array& i_other) + { + // If they're not the same size, they're not the same + if (size() != i_other.size()) + { + return false; + } + + // If they're the same size and point to the same memory, they're the same. + if (iv_data == i_other.iv_data) + { + return true; + } + + auto oitr = i_other.begin(); + auto iter = begin(); + + for(; iter != end(); ++iter, ++oitr) + { + if (*iter != *oitr) + { + return false; + } + } + + return true; + } +} diff --git a/src/ppe/hwpf/plat/src/error_info.C b/src/ppe/hwpf/plat/src/error_info.C new file mode 100644 index 0000000..08cfcb3 --- /dev/null +++ b/src/ppe/hwpf/plat/src/error_info.C @@ -0,0 +1,412 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/src/error_info.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/** + * @file error_info.C + * @brief Implements the error information classes + */ + +#include <stdint.h> +#include <string.h> +#include <plat_trace.H> +#include <error_info.H> +#include <buffer.H> + +namespace fapi2 +{ + /// + /// @brief Constructor + /// + /// @param[in] i_ffdcId FFDC Identifier (used to decode FFDC) + /// @param[in] i_pFfdc Pointer to the FFDC to copy + /// @param[in] i_size Size of the FFDC to copy + /// + ErrorInfoFfdc::ErrorInfoFfdc(const uint32_t i_ffdcId, + const void* i_pFfdc, + const uint32_t i_size): + iv_ffdcId(i_ffdcId), + iv_size(i_size) + { + iv_pFfdc = std::shared_ptr<uint8_t>(new uint8_t[i_size]()); + + // If they passed us a NULL pointer they want to fill + // in the data themselves later. + if (i_pFfdc != nullptr) + { + memcpy(iv_pFfdc.get(), i_pFfdc, i_size); + } + } + + /// + /// @brief Constructor. + /// + /// @param[in] i_hw Hardware to callout + /// @param[in] i_calloutPriority Priority of callout + /// @param[in] i_refTarget Reference to reference target + /// + ErrorInfoHwCallout::ErrorInfoHwCallout( + const HwCallouts::HwCallout i_hw, + const CalloutPriorities::CalloutPriority i_calloutPriority, + const Target<TARGET_TYPE_ALL> & i_refTarget): + iv_hw(i_hw), + iv_calloutPriority(i_calloutPriority), + iv_refTarget(i_refTarget) + {} + + /// + /// @brief Constructor. + /// + /// @param[in] i_procedure Procedure to callout + /// @param[in] i_calloutPriority Priority of callout + /// + ErrorInfoProcedureCallout::ErrorInfoProcedureCallout( + const ProcedureCallouts::ProcedureCallout i_procedure, + const CalloutPriorities::CalloutPriority i_calloutPriority): + iv_procedure(i_procedure), + iv_calloutPriority(i_calloutPriority) + {} + + /// + /// @brief Constructor. + /// + /// @param[in] i_target1 Reference to target on one end of the bus + /// @param[in] i_target2 Reference to target on other end of the bus + /// @param[in] i_calloutPriority Priority of callout + /// + ErrorInfoBusCallout::ErrorInfoBusCallout( + const Target<TARGET_TYPE_ALL> & i_target1, + const Target<TARGET_TYPE_ALL> & i_target2, + const CalloutPriorities::CalloutPriority i_calloutPriority): + iv_target1(i_target1), + iv_target2(i_target2), + iv_calloutPriority(i_calloutPriority) + {} + + /// + /// @brief Constructor. + /// + /// @param[in] i_target Reference to the target to c/d/g + /// @param[in] i_callout True if Target should be called out + /// @param[in] i_deconfigure True if Target should be deconfigured + /// @param[in] i_gard True if Target should be GARDed + /// @param[in] i_priority The priority of any callout + /// + ErrorInfoCDG::ErrorInfoCDG( + const Target<TARGET_TYPE_ALL> & i_target, + const bool i_callout, + const bool i_deconfigure, + const bool i_gard, + const CalloutPriorities::CalloutPriority i_priority): + iv_target(i_target), + iv_callout(i_callout), + iv_calloutPriority(i_priority), + iv_deconfigure(i_deconfigure), + iv_gard(i_gard) + {} + + /// + /// @brief Constructor. + /// + /// @param[in] i_parent Reference to the parent target + /// @oaram[in] i_childType Child target type to c/d/g + /// @param[in] i_callout True if Target should be called out + /// @param[in] i_deconfigure True if Target should be deconfigured + /// @param[in] i_gard True if Target should be GARDed + /// @param[in] i_priority The priority of any callout + /// @param[in] i_childPort Child Port + /// For DIMM children, the MBA port number + /// @param[in] i_childNum Child Number + /// For DIMM children, the dimm socket number + /// For Chip children, the chip position + /// For Chiplet children, the chiplet unit pos + /// + ErrorInfoChildrenCDG::ErrorInfoChildrenCDG( + const Target<TARGET_TYPE_ALL> & i_parentChip, + const TargetType i_childType, + const bool i_callout, + const bool i_deconfigure, + const bool i_gard, + const CalloutPriorities::CalloutPriority i_priority, + const uint8_t i_childPort, const uint8_t i_childNum): + iv_parent(i_parentChip), + iv_childType(i_childType), + iv_callout(i_callout), + iv_calloutPriority(i_priority), + iv_deconfigure(i_deconfigure), + iv_gard(i_gard), + iv_childPort(i_childPort), + iv_childNumber(i_childNum) + {} + + /// + /// @brief Constructor. + /// + /// @param[in] i_trace + /// + ErrorInfoCollectTrace::ErrorInfoCollectTrace( + CollectTraces::CollectTrace i_traceId): + iv_eiTraceId(i_traceId) + {} + + + /// + /// @brief Collect target, buffer or generic FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryFfdc::addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_objects) const + { + // "variable buffer ffdc not yet implemented"); + assert(iv_ffdcSize != EI_FFDC_SIZE_VBUF); + + switch(iv_ffdcSize) + { + case EI_FFDC_SIZE_BUF: + { + const buffer<uint64_t>* object = + static_cast<const buffer<uint64_t>*>(i_objects[iv_ffdcObjIndex]); + + i_info->iv_ffdcs.push_back(std::shared_ptr<ErrorInfoFfdc>( + new ErrorInfoFfdc(iv_ffdcId, object, + sizeof(object)))); + + FAPI_DBG("addErrorInfo: Adding buffer id: 0x%x size: %lu buf: 0x%lx", + iv_ffdcId, sizeof(object), uint64_t(*object)); + } + break; + + case EI_FFDC_SIZE_TARGET: + { + Target<TARGET_TYPE_ALL> object = + *(static_cast<const Target<TARGET_TYPE_ALL>*> + (i_objects[iv_ffdcObjIndex])); + + // Allocate an ErrorInfoFfdc but don't copy anything in to it. + // We can copy the target string once if we copy directly into + // the error info + ErrorInfoFfdc* e = + new ErrorInfoFfdc(iv_ffdcId, nullptr, MAX_ECMD_STRING_LEN); + + toString(object, static_cast<char*>(e->getData()), + MAX_ECMD_STRING_LEN); + i_info->iv_ffdcs.push_back(std::shared_ptr<ErrorInfoFfdc>(e)); + + FAPI_DBG("addErrorInfo: Adding target ffdc id: 0x%x %s", + iv_ffdcId, static_cast<char*>(e->getData())); + } + break; + + default: + i_info->iv_ffdcs.push_back(std::shared_ptr<ErrorInfoFfdc>( + new ErrorInfoFfdc( + iv_ffdcId, + i_objects[iv_ffdcObjIndex], + iv_ffdcSize))); + FAPI_DBG("addErrorInfo: Adding ffdc id 0x%x size: %d", + iv_ffdcId, iv_ffdcSize); + break; + + }; + + return; + } + + /// + /// @brief Collect h/w callout FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryHwCallout::addErrorInfo(std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const + { + // If the index is 0xFF, we use an empty target. Otherwise the + // target is taken from the object arrary with the given index. + const fapi2::Target<TARGET_TYPE_ALL> target = + iv_refObjIndex == 0xFF ? + fapi2::Target<TARGET_TYPE_ALL>() : + *(static_cast<const fapi2::Target<TARGET_TYPE_ALL>*> + (i_object[iv_refObjIndex])); + + ErrorInfoHwCallout* ei = new ErrorInfoHwCallout( + static_cast<HwCallouts::HwCallout>(iv_hw), + static_cast<CalloutPriorities::CalloutPriority>(iv_calloutPriority), + target); + + FAPI_DBG("addErrorInfo: Adding hw callout target: 0x%lx hw: %d, pri: %d", + ei->iv_refTarget.get(), ei->iv_hw, ei->iv_calloutPriority); + + i_info->iv_hwCallouts.push_back(std::shared_ptr<ErrorInfoHwCallout>(ei)); + } + + /// + /// @brief Collect proc callout FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryProcCallout::addErrorInfo( + std::shared_ptr<ErrorInfo> i_info, + const void* const* ) const + { + ErrorInfoProcedureCallout* ei = new ErrorInfoProcedureCallout( + static_cast<ProcedureCallouts::ProcedureCallout>(iv_procedure), + static_cast<CalloutPriorities::CalloutPriority>(iv_calloutPriority)); + + // Add the ErrorInfo + FAPI_DBG("addErrorInfo: Adding proc callout, proc: %d, pri: %d", + ei->iv_procedure, ei->iv_calloutPriority); + + i_info->iv_procedureCallouts.push_back( + std::shared_ptr<ErrorInfoProcedureCallout>(ei)); + } + + /// + /// @brief Collect bus callout FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryBusCallout::addErrorInfo( + std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const + { + // We need to add a procedure callout as well as a bus callout + ErrorInfoEntryProcCallout(ProcedureCallouts::BUS_CALLOUT, + iv_calloutPriority).addErrorInfo(i_info, + i_object); + + // Now add our bus callout, but drop the priority by one. + ErrorInfoBusCallout* ei = new ErrorInfoBusCallout( + // First target + *(static_cast<const fapi2::Target<TARGET_TYPE_ALL>*> + (i_object[iv_endpoint1ObjIndex])), + + // Second target + *(static_cast<const fapi2::Target<TARGET_TYPE_ALL>*> + (i_object[iv_endpoint2ObjIndex])), + + // Priority, one lower. + (iv_calloutPriority == CalloutPriorities::HIGH) ? + CalloutPriorities::MEDIUM : CalloutPriorities::LOW); + + FAPI_DBG("addErrorInfo: Adding bus callout t1: 0x%lx t2: 0x%lx, pri: %d", + ei->iv_target1.get(), ei->iv_target2.get(), + ei->iv_calloutPriority); + + i_info->iv_busCallouts.push_back( + std::shared_ptr<ErrorInfoBusCallout>(ei)); + } + + /// + /// @brief Collect h/w target cdg FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryTargetCDG::addErrorInfo( + std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const + { + ErrorInfoCDG* ei = new + ErrorInfoCDG( + *(static_cast<const fapi2::Target<TARGET_TYPE_ALL>*> + (i_object[iv_targetObjIndex])), + iv_callout, + iv_deconfigure, + iv_gard, + static_cast<CalloutPriorities::CalloutPriority> + (iv_calloutPriority) + ); + + FAPI_DBG("addErrorInfo: Adding target 0x%lx cdg (%d:%d:%d), pri: %d", + ei->iv_target.get(), + ei->iv_callout, ei->iv_deconfigure, + ei->iv_gard, ei->iv_calloutPriority); + + // Add the ErrorInfo + i_info->iv_CDGs.push_back(std::shared_ptr<ErrorInfoCDG>(ei)); + } + + /// + /// @brief Collect h/w children cdg FFDC information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryChildrenCDG::addErrorInfo( + std::shared_ptr<ErrorInfo> i_info, + const void* const* i_object) const + { + ErrorInfoChildrenCDG* ei = new ErrorInfoChildrenCDG( + *(static_cast<const fapi2::Target<TARGET_TYPE_ALL>*> + (i_object[iv_parentObjIndex])), + static_cast<fapi2::TargetType>(iv_childType), + iv_callout, + iv_deconfigure, + iv_gard, + static_cast<CalloutPriorities::CalloutPriority> + (iv_calloutPriority), + iv_childPort, + iv_childNumber); + + FAPI_DBG("addErrorInfo: Adding children cdg (%d:%d:%d), type:" + " 0x%08x, pri: %d", + ei->iv_callout, ei->iv_deconfigure, ei->iv_gard, + ei->iv_childType, ei->iv_calloutPriority); + + // Add the ErrorInfo + i_info->iv_childrenCDGs.push_back( + std::shared_ptr<ErrorInfoChildrenCDG>(ei)); + } + + /// + /// @brief Collect trace information to this ffdc + /// object + /// @param[in] A pointer to the error info we're collecting + /// @param[in] A pointer to the objects + /// @return void + /// + void ErrorInfoEntryCollectTrace::addErrorInfo( + std::shared_ptr<ErrorInfo> i_info, + const void* const* ) const + { + ErrorInfoCollectTrace* ei = new ErrorInfoCollectTrace( + static_cast<CollectTraces::CollectTrace>(iv_eieTraceId)); + + FAPI_DBG("addErrorInfo: Adding trace: 0x%x", ei->iv_eiTraceId); + + // Add the ErrorInfo + i_info->iv_traces.push_back(std::shared_ptr<ErrorInfoCollectTrace>(ei)); + } + +}; diff --git a/src/ppe/hwpf/plat/src/fapi2ppefiles.mk b/src/ppe/hwpf/plat/src/fapi2ppefiles.mk new file mode 100644 index 0000000..3adeec6 --- /dev/null +++ b/src/ppe/hwpf/plat/src/fapi2ppefiles.mk @@ -0,0 +1,51 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/hwpf/plat/src/fapi2ppefiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file fapi2ppefiles.mk +# +# @brief mk for including fapi2 object files +# +# @page ChangeLogs Change Logs +# @section fapi2ppefiles.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# Object Files +########################################################################## + + +FAPI2-C-SOURCES += fapi2PlatAttributeService.C \ + plat_utils.C + +FAPI2-S-SOURCES = + +FAPI2LIB_OBJECTS += $(FAPI2-C-SOURCES:.C=.o) $(FAPI2-S-SOURCES:.S=.o) + diff --git a/src/ppe/hwpf/plat/src/ffdc.C b/src/ppe/hwpf/plat/src/ffdc.C new file mode 100644 index 0000000..d200e4f --- /dev/null +++ b/src/ppe/hwpf/plat/src/ffdc.C @@ -0,0 +1,59 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/src/ffdc.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/** + * @file ffdc.C + * @brief Implements the FirstFailureData class + */ + +#include <plat_trace.H> +#include <ffdc.H> +#include <error_info.H> + +namespace fapi2 +{ + + /// + /// @brief Add error information to this ffdc object + /// @param[in] A pointer to a list of objects + /// @param[in] A pointer to the list of entries + /// @param[in] The count of how many entries there are + /// @return void + /// + template<> + void FirstFailureData<ReturnCode>::addErrorInfo( + const void* const* i_pObjects, + const ErrorInfoEntry* i_pEntries, + const uint8_t i_count) + { + FAPI_DBG("%d entries", i_count); + for (uint32_t i = 0; i < i_count; i++) + { + i_pEntries[i].addErrorInfo(iv_info, i_pObjects); + } + } + + + +}; diff --git a/src/ppe/hwpf/plat/src/plat_utils.C b/src/ppe/hwpf/plat/src/plat_utils.C new file mode 100644 index 0000000..2b6773a --- /dev/null +++ b/src/ppe/hwpf/plat/src/plat_utils.C @@ -0,0 +1,137 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/src/plat_utils.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/** + * @file plat_utils.C + * @brief Implements fapi2 common utilities + */ + +#include <stdint.h> +#include <plat_trace.H> +#include <return_code.H> +#include <error_info.H> + +namespace fapi2 +{ + /// + /// @brief Log an error. + /// + void logError( + fapi2::ReturnCode & io_rc, + fapi2::errlSeverity_t i_sev = fapi2::FAPI2_ERRL_SEV_UNRECOVERABLE, + bool i_unitTestError = false ) + { + // To keep the compiler from complaing about i_sevbeing unused. + static_cast<void>(i_sev); + static_cast<void>(i_unitTestError); + + FAPI_DBG("logging 0x%lx.", uint64_t(io_rc)); + + // Iterate over the vectors and output what is in them. + const ErrorInfo* ei = io_rc.getErrorInfo(); + + FAPI_DBG("ffdcs: %lu", ei->iv_ffdcs.size()); + for( auto i = ei->iv_ffdcs.begin(); i != ei->iv_ffdcs.end(); ++i ) + { + uint32_t sz; + (*i)->getData(sz); + FAPI_DBG("\tid: 0x%x size %d", (*i)->getFfdcId(), sz); + } + + FAPI_DBG("hwCallouts: %lu", ei->iv_hwCallouts.size()); + for( auto i = ei->iv_hwCallouts.begin(); i != ei->iv_hwCallouts.end(); + ++i ) + { + FAPI_DBG("\thw: %d pri %d target: 0x%lx", + (*i)->iv_hw, (*i)->iv_calloutPriority, + (*i)->iv_refTarget.get()); + } + + FAPI_DBG("procedureCallouts: %lu", ei->iv_procedureCallouts.size()); + for( auto i = ei->iv_procedureCallouts.begin(); + i != ei->iv_procedureCallouts.end(); ++i ) + { + FAPI_DBG("\tprocedure: %d pri %d", + (*i)->iv_procedure, (*i)->iv_calloutPriority); + } + + FAPI_DBG("busCallouts: %lu", ei->iv_busCallouts.size()); + for( auto i = ei->iv_busCallouts.begin(); i != ei->iv_busCallouts.end(); + ++i ) + { + FAPI_DBG("\tbus: t1: 0x%lx t2: 0x%lx pri: %d", + (*i)->iv_target1.get(), (*i)->iv_target2.get(), + (*i)->iv_calloutPriority); + } + + + FAPI_DBG("cdgs: %lu", ei->iv_CDGs.size()); + for( auto i = ei->iv_CDGs.begin(); i != ei->iv_CDGs.end(); ++i ) + { + FAPI_DBG("\ttarget: 0x%lx co: %d dc: %d gard: %d pri: %d", + (*i)->iv_target.get(), + (*i)->iv_callout, + (*i)->iv_deconfigure, + (*i)->iv_gard, + (*i)->iv_calloutPriority); + + } + + FAPI_DBG("childrenCDGs: %lu", ei->iv_childrenCDGs.size()); + for( auto i = ei->iv_childrenCDGs.begin(); + i != ei->iv_childrenCDGs.end(); ++i ) + { + FAPI_DBG("\tchildren: parent 0x%lx co: %d dc: %d gard: %d pri: %d", + (*i)->iv_parent.get(), + (*i)->iv_callout, + (*i)->iv_deconfigure, + (*i)->iv_gard, + (*i)->iv_calloutPriority); + } + + FAPI_DBG("traces: %lu", ei->iv_traces.size()); + for( auto i = ei->iv_traces.begin(); i != ei->iv_traces.end(); ++i ) + { + FAPI_DBG("\ttraces: 0x%x", (*i)->iv_eiTraceId); + } + + // Release the ffdc information now that we're done with it. + io_rc.forgetData(); + + } + + /// + /// @brief Delay this thread. + /// + ReturnCode delay(uint64_t i_nanoSeconds, uint64_t i_simCycles) + { + // void statements to keep the compiler from complaining + // about unused variables. + static_cast<void>(i_nanoSeconds); + static_cast<void>(i_simCycles); + + // replace with platform specific implementation + return FAPI2_RC_SUCCESS; + } +}; diff --git a/src/ppe/hwpf/plat/src/target.C b/src/ppe/hwpf/plat/src/target.C new file mode 100644 index 0000000..2439a3f --- /dev/null +++ b/src/ppe/hwpf/plat/src/target.C @@ -0,0 +1,35 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/hwpf/plat/src/target.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,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 */ + +#include <target.H> + +namespace fapi2 +{ + std::vector Target::getChildren(void) const + +}; + + + diff --git a/src/ppe/hwpf/plat/target_map b/src/ppe/hwpf/plat/target_map new file mode 100755 index 0000000..4ea3c0d --- /dev/null +++ b/src/ppe/hwpf/plat/target_map @@ -0,0 +1,49 @@ + TARGET_TYPE_NONE = 0x00000000, + TARGET_TYPE_SYSTEM = 0x00000001, + TARGET_TYPE_DIMM = 0x00000002, + TARGET_TYPE_PROC_CHIP = 0x00000004, + TARGET_TYPE_MEMBUF_CHIP = 0x00000008, + TARGET_TYPE_EX = 0x00000010, + TARGET_TYPE_MBA = 0x00000020, + TARGET_TYPE_MCS = 0x00000040, + TARGET_TYPE_XBUS = 0x00000080, + TARGET_TYPE_ABUS = 0x00000100, + TARGET_TYPE_L4 = 0x00000200, + TARGET_TYPE_CORE = 0x00000400, + TARGET_TYPE_EQ = 0x00000800, + TARGET_TYPE_MCA = 0x00001000, + TARGET_TYPE_MCBIST = 0x00002000, + TARGET_TYPE_MIA = 0x00004000, + TARGET_TYPE_MIS = 0x00008000, + TARGET_TYPE_DMI = 0x00010000, + TARGET_TYPE_OBUS = 0x00020000, + TARGET_TYPE_NV = 0x00040000, + TARGET_TYPE_SBE = 0x00080000, + TARGET_TYPE_PPE = 0x00100000, + TARGET_TYPE_PERV = 0x00200000, + TARGET_TYPE_PEC = 0x00400000, + TARGET_TYPE_PHB = 0x00800000, + TARGET_TYPE_ALL = 0xFFFFFFFF + + + Perv 0x01 +N0 0x02 +N1 0x03 +N2 0x04 +N3 0x05 +XB 0x06 +MC0 0x07 +MC1 0x08 +OB0 0x09 +OB1 0x0A +OB2 0x0B +OB3 0x0C +PCI0 0x0D +PCI1 0x0E +PCI2 0x0F + + + + + + diff --git a/src/ppe/import/.empty b/src/ppe/import/.empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/import/.empty diff --git a/src/ppe/include/ppe_compiler.mk b/src/ppe/include/ppe_compiler.mk new file mode 100755 index 0000000..2595787 --- /dev/null +++ b/src/ppe/include/ppe_compiler.mk @@ -0,0 +1,83 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/include/ppe_compiler.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# Make header to set up PPE Compiler +# +ifndef CC_VERSION +export CC_VERSION = 4.8.3 +endif + +ifndef CC_TARGET +export CC_TARGET = powerpc-buildroot-linux-gnu +endif + +# GCC libraries +ifndef LIB_GCC_DIR +export LIB_GCC_DIR = $(CC_ROOT)/usr/lib/gcc/$(CC_TARGET)/$(CC_VERSION) +endif +LIB_DIRS += -L$(LIB_GCC_DIR) + +# GCC libraries +ifndef LIB_GCC_BASE +export LIB_GCC_BASE = $(CC_ROOT)/usr/lib/gcc/$(CC_TARGET) +endif +LIB_DIRS += -L$(LIB_GCC_BASE) + +# GCC libraries +ifndef LIB_BASE +export LIB_BASE = $(CC_ROOT)/usr/lib +endif +LIB_DIRS += -L$(LIB_BASE) + +# Shared Object C and C++ libraries +ifndef LIB_TARGET +export LIB_TARGET = $(CC_ROOT)/usr/$(CC_TARGET)/lib +endif +#CLIBS += $(LIB_TARGET)/libstdc++.a +#LIB_DIRS += -L$(LIB_TARGET) + +# Static C and C++ libraries +ifndef LIB_CLIB_DIR +export LIB_CLIB_DIR = $(CC_ROOT)/usr/$(CC_TARGET)/sysroot/lib +endif +LIB_DIRS += -L$(LIB_CLIB_DIR) + +# Runtime Static C and C++ libraries +ifndef LIB_CULIB_DIR +export LIB_CULIB_DIR = $(CC_ROOT)/usr/$(CC_TARGET)/sysroot/usr/lib +endif +LIB_DIRS += -L$(LIB_CULIB_DIR) + +GCCLIBS += $(LIB_CULIB_DIR)/libstdc++.a +GCCLIBS += $(LIB_CULIB_DIR)/libm.a +GCCLIBS += $(LIB_CULIB_DIR)/libc.a + +ifdef ENABLE_UCLIB +GCCLIBS += $(LIB_CULIB_DIR)/uclibc_nonshared.a +GCCLIBS += $(LIB_CULIB_DIR)/crt1.o +GCCLIBS += $(LIB_CULIB_DIR)/crti.o +endif + +GCCLIBS += $(LIB_GCC_DIR)/libgcc.a +GCCLIBS += $(LIB_GCC_DIR)/libgcc_eh.a diff --git a/src/ppe/include/proc_hcd_common.H b/src/ppe/include/proc_hcd_common.H new file mode 100644 index 0000000..7fe5042 --- /dev/null +++ b/src/ppe/include/proc_hcd_common.H @@ -0,0 +1,44 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/include/proc_hcd_common.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PROC_HCD_COMMON_H +#define __PROC_HCD_COMMON_H + +/// \file proc_hcd_common.H +/// \brief Standard bit-manipulation macros (C and Assembler) for PORE code + +/// \defgroup be64_bits Bit manipulation for 64-bit Big-Endian values +/// +/// \note These macros only work in the assembler context because we build our +/// assemblers to do 64-bit arithmetic, which is required for PORE assembly. +/// +/// @{ + +/// Create a multi-bit mask of \a n bits starting at bit \a b +#define BITS(b, n) ((ULL(0xffffffffffffffff) << (64 - (n))) >> (b)) + +/// Create a single bit mask at bit \a b +#define BIT(b) BITS((b), 1) + +#endif // __PROC_HCD_COMMON_H diff --git a/src/ppe/lib/.empty b/src/ppe/lib/.empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/lib/.empty diff --git a/src/ppe/ops/.empty b/src/ppe/ops/.empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/ops/.empty diff --git a/src/ppe/pk/.empty b/src/ppe/pk/.empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/pk/.empty diff --git a/src/ppe/pk/README b/src/ppe/pk/README new file mode 100644 index 0000000..2227ec3 --- /dev/null +++ b/src/ppe/pk/README @@ -0,0 +1,8 @@ +Subdirectories are organized as follows: + +kernel: Architecture-independent kernel code +ppe42: Kernel code that is common for all ppe42 instances +std: External interrupt support for standard ppe42 instances (SBE, CME, etc.) +gpe: External interrupt support for ppe42 instances residing in the OCC complex +ppe: Support for ppe42 instances that do not require or have external interrupts +trace: Kernel trace support diff --git a/src/ppe/pk/gpe/Makefile b/src/ppe/pk/gpe/Makefile new file mode 100644 index 0000000..bee7ad8 --- /dev/null +++ b/src/ppe/pk/gpe/Makefile @@ -0,0 +1,74 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/gpe/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# This Makefile compiles all of the PK code required for the GPE port +# of PK. See the "pk.mk" file in this directory. + +#all generated files from this makefile will end up in obj/$(IMAGE_NAME)/pk +export SUB_OBJDIR = /pk + +include img_defs.mk +include pkgpefiles.mk + +ifeq "$(PK_TIMER_SUPPORT)" "1" +GPE_OBJECTS += ${GPE-TIMER-C-SOURCES:.c=.o} ${GPE-TIMER-S-SOURCES:.S=.o} +endif + +ifeq "$(PK_THREAD_SUPPORT)" "1" +GPE_OBJECTS += ${GPE-THREAD-C-SOURCES:.c=.o} ${GPE-THREAD-S-SOURCES:.S=.o} +endif + +ifeq "$(GPE_ASYNC_SUPPORT)" "1" +GPE_OBJECTS += ${GPE-ASYNC-C-SOURCES:.c=.o} ${GPE-ASYNC-S-SOURCES:.S=.o} +endif + +OBJS := $(addprefix $(OBJDIR)/, $(GPE_OBJECTS)) + +libpk.a: kernel ppe42 trace gpe + $(AR) crs $(OBJDIR)/libpk.a $(OBJDIR)/*.o + +.PHONY: clean gpe kernel ppe42 trace +gpe: $(OBJS) + +trace: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../trace + +kernel: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../kernel + +ppe42: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../ppe42 + + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +clean: + rm -fr $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/pk/gpe/gpe.h b/src/ppe/pk/gpe/gpe.h new file mode 100644 index 0000000..ef5ad01 --- /dev/null +++ b/src/ppe/pk/gpe/gpe.h @@ -0,0 +1,59 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/gpe/gpe.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __GPE_H__ +#define __GPE_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp.h +/// \brief The GPE environment for PK. + +// This is a 'circular' reference in PK, but included here to simplify PGAS +// programming. + +#ifndef HWMACRO_GPE +#define HWMACRO_GPE +#include "ppe42.h" +#endif + +#include "ocb_register_addresses.h" +#include "gpe_common.h" + +/* +#include "pcbs_register_addresses.h" +#include "pcbs_firmware_registers.h" + +#include "tod_register_addresses.h" +#include "tod_firmware_registers.h" + +#include "plb_arbiter_register_addresses.h" +#include "plb_arbiter_firmware_registers.h" + +*/ + +#endif /* __GPE_H__ */ diff --git a/src/ppe/pk/gpe/gpe_common.h b/src/ppe/pk/gpe/gpe_common.h new file mode 100644 index 0000000..debae8e --- /dev/null +++ b/src/ppe/pk/gpe/gpe_common.h @@ -0,0 +1,89 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/gpe/gpe_common.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __GPE_COMMON_H__ +#define __GPE_COMMON_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file gpe_common.h +/// \brief Common header for GPE +/// +/// This header is maintained as part of the PK port for GPE, but needs to be +/// physically present in the PMX area to allow dropping PMX code as a whole +/// to other teams. + +// -*- WARNING: This file is maintained as part of PK. Do not edit in -*- +// -*- the PMX area as your edits will be lost. -*- + +#ifndef __ASSEMBLER__ +#include <stdint.h> +#endif + +#include "occhw_common.h" + +/// Each GPE instance has it's own interrupt status register these macros +/// are added for convenience in accessing the correct register +#define GPE_GISR0(instance_id) (OCB_G0ISR0 + (instance_id * 8)) +#define GPE_GISR1(instance_id) (OCB_G0ISR1 + (instance_id * 8)) + +#ifdef __ASSEMBLER__ +/// This macro contains GPE specific code for determining what IRQ caused the +/// external exception handler to be invoked by the PPE + +/// Check for interrupts pending in status register 0 while the IRQ is +/// computed. The IRQ is expected to be stored in r4. If no IRQ is +/// pending then load the phantom irq # (EXTERNAL_IRQS). +/// +/// r1, r2, r3, and r13 must not be modified. All other registers may be used. +/// + .macro hwmacro_get_ext_irq + + _lwzi %r5, %r5, GPE_GISR0(APPCFG_OCC_INSTANCE_ID) + cntlzw %r4, %r5 + cmpwible %r4, 31, call_external_irq_handler #branch if irq is lt or eq to 31 + + ## No IRQ pending in interrupt set 0. Try set 1. + ## Note: irq # will be 64 (EXTERNAL_IRQS) if no bits were set in either register + + _lwzi %r6, %r6, GPE_GISR1(APPCFG_OCC_INSTANCE_ID) + cntlzw %r4, %r6 + addi %r4, %r4, 32 + + .endm + + +/// Redirect the .hwmacro_irq_cfg_bitmaps macro to call our macro that is common for both +/// GPE's and the 405 inside the OCC complex. This is called from the ppe42_exceptions.S +/// file. + .macro .hwmacro_irq_cfg_bitmaps + .occhw_irq_cfg_bitmaps + .endm +#endif /* __ASSEMBLER__ */ + +#endif /* __GPE_COMMON_H__ */ diff --git a/src/ppe/pk/gpe/gpe_init.c b/src/ppe/pk/gpe/gpe_init.c new file mode 100644 index 0000000..9692aad --- /dev/null +++ b/src/ppe/pk/gpe/gpe_init.c @@ -0,0 +1,146 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/gpe/gpe_init.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file gpe_init.c +/// \brief PK initialization for GPE +/// +/// The entry points in this routine are used during initialization. This +/// code space can be deallocated and reassigned after application +/// initialization if required. + +#include "pk.h" +#include "ocb_register_addresses.h" + +/// GPE environment initial setup. +/// +/// This is setup common to all GPE HW Macro applications. This setup takes place +/// during boot, before main() is called. + +void +__hwmacro_setup(void) +{ + uint64_t oirrA; + uint64_t oirrB; + uint64_t oirrC; + uint64_t owned_actual; + uint64_t reverse_polarity; + + //verify that this code is running on the correct GPE instance (one time check) + if((mfspr(SPRN_PIR) & PIR_PPE_INSTANCE_MASK) != APPCFG_OCC_INSTANCE_ID) + { + //APPCFG_OCC_INSTANCE_ID does not match actual instance ID! + PK_PANIC(OCCHW_INSTANCE_MISMATCH); + } + +#if (APPCFG_OCC_INSTANCE_ID == OCCHW_IRQ_ROUTE_OWNER) + //If this instance is the owner of the interrupt routting registers + //then write the routing registers for all OCC interrupts. + //This instance must be the first instance to run within the OCC + //This will be done while all external interrupts are masked. + PKTRACE("Initializing External Interrupt Routing Registers"); + out32(OCB_OIMR0_OR, 0xffffffff); + out32(OCB_OIMR1_OR, 0xffffffff); + out32(OCB_OIRR0A, (uint32_t)(g_ext_irqs_routeA >> 32)); + out32(OCB_OIRR1A, (uint32_t)g_ext_irqs_routeA); + out32(OCB_OIRR0B, (uint32_t)(g_ext_irqs_routeB >> 32)); + out32(OCB_OIRR1B, (uint32_t)g_ext_irqs_routeB); + out32(OCB_OIRR0C, (uint32_t)(g_ext_irqs_routeC >> 32)); + out32(OCB_OIRR1C, (uint32_t)g_ext_irqs_routeC); +#endif + + //Determine from the routing registers which irqs are owned by this instance + //NOTE: If a bit is not set in the routeA register, it is not owned by a GPE + + oirrA = ((uint64_t)in32(OCB_OIRR0A)) << 32; + oirrA |= in32(OCB_OIRR1A); + oirrB = ((uint64_t)in32(OCB_OIRR0B)) << 32; + oirrB |= in32(OCB_OIRR1B); + oirrC = ((uint64_t)in32(OCB_OIRR0C)) << 32; + oirrC |= in32(OCB_OIRR1C); + + //All interrupts routed to a GPE will have a bit set in routeA + owned_actual = oirrA; + + //wittle it down by bits in the routeB register +#if APPCFG_OCC_INSTANCE_ID & 0x2 + owned_actual &= oirrB; +#else + owned_actual &= ~oirrB; +#endif + + //wittle it down further by bits in the routeC register +#if APPCFG_OCC_INSTANCE_ID & 0x1 + owned_actual &= oirrC; +#else + owned_actual &= ~oirrC; +#endif + + //Panic if we don't own the irqs we were expecting + //NOTE: we don't panic if we are given more IRQ's than expected + if((owned_actual & g_ext_irqs_owned) != g_ext_irqs_owned) + { + //IRQ's were not routed to us correctly. + PK_PANIC(OCC_IRQ_ROUTING_ERROR); + } + + //Mask all external interrupts owned by this instance + //(even the ones given to us that we weren't expecting) + out32(OCB_OIMR0_OR, (uint32_t)(owned_actual >> 32)); + out32(OCB_OIMR1_OR, (uint32_t)owned_actual); + + //Set the interrupt type for all interrupts owned by this instance + out32(OCB_OITR0_CLR, (uint32_t)(g_ext_irqs_owned >> 32)); + out32(OCB_OITR1_CLR, (uint32_t)g_ext_irqs_owned); + out32(OCB_OITR0_OR, (uint32_t)(g_ext_irqs_type >> 32)); + out32(OCB_OITR1_OR, (uint32_t)g_ext_irqs_type); + + //Set the interrupt polarity for all interrupts owned by this instance + out32(OCB_OIEPR0_CLR, (uint32_t)(g_ext_irqs_owned >> 32)); + out32(OCB_OIEPR1_CLR, (uint32_t)g_ext_irqs_owned); + out32(OCB_OIEPR0_OR, (uint32_t)(g_ext_irqs_polarity >> 32)); + out32(OCB_OIEPR1_OR, (uint32_t)g_ext_irqs_polarity); + + //clear the status of all external interrupts owned by this instance + out32(OCB_OISR0_CLR, ((uint32_t)(g_ext_irqs_owned >> 32))); + out32(OCB_OISR1_CLR, ((uint32_t)g_ext_irqs_owned)); + + //set the status for interrupts that have reverse polarity + reverse_polarity = ~g_ext_irqs_polarity & g_ext_irqs_owned; + out32(OCB_OISR0_OR, ((uint32_t)(reverse_polarity >> 32))); + out32(OCB_OISR1_OR, ((uint32_t)reverse_polarity)); + + //Unmask the interrupts owned by this instance that are to be enabled by default + out32(OCB_OIMR0_CLR, (uint32_t)(g_ext_irqs_enable >> 32)); + out32(OCB_OIMR1_CLR, (uint32_t)g_ext_irqs_enable); + + //Wait for the last out32 operation to complete + sync(); + +} diff --git a/src/ppe/pk/gpe/gpe_irq.h b/src/ppe/pk/gpe/gpe_irq.h new file mode 100644 index 0000000..6a71765 --- /dev/null +++ b/src/ppe/pk/gpe/gpe_irq.h @@ -0,0 +1,271 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/gpe/gpe_irq.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __GPE_IRQ_H__ +#define __GPE_IRQ_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file occhw_irq.h +/// \brief GPE-OCCHW Interrupt handling for PK +/// +/// The OCCHW interrupt controller supports a maximum of 64 interrupts, split +/// into 2 x 32-bit non-cascaded interrupt controllers with simple OR +/// combining of the interrupt signals. +/// +/// The OCB interrupt controller allows interrupt status to be set directly by +/// software, as well as providing a mode that causes an enabled pending +/// interrupt to trigger an Unconditional Debug Event. The OCB interrupt +/// controller contains a 'mask' register, unlike other 405 interrupt +/// controllers that have an 'enable' register. The OCCHW mask and status +/// registers also have atomic CLR/OR function so that it is never necessary +/// to enter a critical section to enable/disable/clear interrupts and +/// interrupt status. + +#include "occhw_common.h" +#include "ocb_register_addresses.h" +#include "ppe42.h" + +#ifndef __ASSEMBLER__ + +/// Enable an interrupt by clearing the mask bit. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_enable(PkIrqId irq) +{ + out32(OCCHW_OIMR_CLR(irq), OCCHW_IRQ_MASK32(irq)); +} + + +/// Disable an interrupt by setting the mask bit. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_disable(PkIrqId irq) +{ + out32(OCCHW_OIMR_OR(irq), OCCHW_IRQ_MASK32(irq)); +} + + +/// Clear interrupt status with an CLR mask. Only meaningful for +/// edge-triggered interrupts. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_status_clear(PkIrqId irq) +{ + out32(OCCHW_OISR_CLR(irq), OCCHW_IRQ_MASK32(irq)); +} + + +/// Get IRQ status as a 0 or non-0 integer + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline int +pk_irq_status_get(PkIrqId irq) +{ + return (in32(OCCHW_OISR(irq)) & OCCHW_IRQ_MASK32(irq)) != 0; +} + + +/// Set or clear interrupt status explicitly. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_status_set(PkIrqId irq, int value) +{ + if (value) { + out32(OCCHW_OISR_OR(irq), OCCHW_IRQ_MASK32(irq)); + } else { + out32(OCCHW_OISR_CLR(irq), OCCHW_IRQ_MASK32(irq)); + } +} + + +#endif /* __ASSEMBLER__ */ + +/// \page occhw_irq_macros OCCHW IRQ API Assembler Macros +/// +/// These macros encapsulate the PK API for the OCCHW interrupt +/// controller. These macros require 2 scratch registers in addition to the \c +/// irq parameter register passed into the handler from PK interrupt +/// dispatch. These macros also modify CR0. +/// +/// \arg \c rirq A register that holds the \c irq parameter passed to +/// the handler from PK interrupt dispatch. This register is not +/// modified. +/// \arg \c rmask A scratch register - At the end of macro execution this +/// register contains the 32-bit mask form of the irq. +/// +/// \arg \c raddr A scratch register - At the end of macro execution this +/// register holds the address of the interrupt +/// controller facility that implements the action. +/// +/// \arg \c imm An immediate (0/non-0) value for certain macros. +/// +/// Forms: +/// +/// \b _pk_irq_enable \a rirq, \a rmask, \a raddr - Enable an \c irq. \n +/// \b _pk_irq_disable \a rirq, \a rmask, \a raddr - Disable an \c irq. \n +/// \b _pk_irq_status_clear \a rirq, \a rmask, \a raddr - Clear \c irq +/// interrupt status. \n +/// \b _pk_irq_status_set \a rirq, \a rmask, \a raddr, \a imm - Set \c irq status +/// with an immediate (0/non-0) value. \n +/// +/// \todo Once the logic design is locked down, revisit whether these macros +/// (and C-code versions) can be implemented without branching. This could be +/// done in theory by converting bit 26 into the byte offset between addresses +/// in interupt controller 0 and interrupt controller 1 - assuming the +/// distances are all the same power-of-two. +/// +/// \cond + +// IRQ numbers are in the range 0..63. IRQs are converted to the 32-bit +// residue used to compute the mask. CR0 is set as a test of IRQ > 32 - the +// register \c raddr is used as scratch for these computations. Hopefully the +// local labels 888 and 999 are unique enough. + +// Register names must be compared as strings - e.g., %r0 is not +// a symbol, it is converted to "0" by the assembler. + +#ifdef __ASSEMBLER__ + + .macro .two_unique, ra, rb + .ifnc \ra, \rb + .exitm + .endif + .error "Both register arguments must be unique" + .endm + + + .macro .three_unique, ra, rb, rc + .ifnc \ra, \rb + .ifnc \rb, \rc + .ifnc \ra, \rc + .exitm + .endif + .endif + .endif + .error "All three register arguments must be unique" + .endm + + + .macro _occhw_irq_or_mask, rirq:req, rmask:req + .two_unique \rirq, \rmask + lis \rmask, 0x8000 + srw \rmask, \rmask, \rirq + .endm + + .macro _occhw_irq_clr_mask, rirq:req, rmask:req + .two_unique \rirq, \rmask + _occhw_irq_or_mask \rirq, \rmask + .endm + + + .macro _pk_irq_enable, rirq:req, rmask:req, raddr:req + .three_unique \rirq, \rmask, \raddr + + andi. \raddr, \rirq, 0x20 + clrlwi \raddr, \rirq, 27 + _occhw_irq_clr_mask \raddr, \rmask + bne- 888f + _stwi \rmask, \raddr, OCB_OIMR0_CLR + b 999f +888: + _stwi \rmask, \raddr, OCB_OIMR1_CLR +999: + eieio + .endm + + + .macro _pk_irq_disable, rirq:req, rmask:req, raddr:req + .three_unique \rirq, \rmask, \raddr + + andi. \raddr, \rirq, 0x20 + clrlwi \raddr, \rirq, 27 + _occhw_irq_or_mask \raddr, \rmask + bne- 888f + _stwi \rmask, \raddr, OCB_OIMR0_OR + b 999f +888: + _stwi \rmask, \raddr, OCB_OIMR1_OR +999: + eieio + .endm + + + .macro _pk_irq_status_clear, rirq:req, rmask:req, raddr:req + .three_unique \rirq, \rmask, \raddr + + andi. \raddr, \rirq, 0x20 + clrlwi \raddr, \rirq, 27 + _occhw_irq_clr_mask \raddr, \rmask + bne- 888f + _stwi \rmask, \raddr, OCB_OISR0_CLR + b 999f +888: + _stwi \rmask, \raddr, OCB_OISR1_CLR +999: + eieio + .endm + + + .macro _pk_irq_status_set, rirq:req, rmask:req, raddr:req, imm:req + .three_unique \rirq, \rmask, \raddr + + andi. \raddr, \rirq, 0x20 + clrlwi \raddr, \rirq, 27 + + .if \imm + _occhw_irq_or_mask \raddr, \rmask + bne- 888f + _stwi \rmask, \raddr, OCB_OISR0_OR + b 999f +888: + _stwi \rmask, \raddr, OCB_OISR1_OR + + .else + + _occhw_irq_clr_mask \raddr, \rmask + bne- 888f + _stwi \rmask, \raddr, OCB_OISR0_CLR + b 999f +888: + _stwi \rmask, \raddr, OCB_OISR1_CLR + .endif + +999: + eieio + .endm + +#endif /* __ASSEMBLER__ */ + +/// \endcond + +#endif /* __GPE_IRQ_H__ */ diff --git a/src/ppe/pk/gpe/gpe_irq_init.c b/src/ppe/pk/gpe/gpe_irq_init.c new file mode 100644 index 0000000..995ebac --- /dev/null +++ b/src/ppe/pk/gpe/gpe_irq_init.c @@ -0,0 +1,130 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/gpe/gpe_irq_init.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file gpe_irq_init.c +/// \brief OCCHW IRQ initialization code for PK +/// +/// The entry points in this file are initialization rotines that could be +/// eliminated/deallocated by the application to free up storage if they are +/// no longer needed after initialization. + +#include "pk.h" + +/// Define the polarity and trigger condition for an interrupt. +/// +/// It is up to the application to take care of any side effects that may +/// occur from programming or reprogramming the interrupt controller. For +/// example, changing edge/level sensitivity or active level may set or clear +/// interrupt status in the controller. +/// +/// Note that PK allows this API to be called from any context, and changes +/// to the interrupt controller are made from a critical section. +/// +/// Return values other then PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_ARGUMENT_IRQ_SETUP One or more arguments are invalid, +/// including an invalid \a irq, or invalid \a polarity or \a trigger parameters. + +int +pk_irq_setup(PkIrqId irq, + int polarity, + int trigger) +{ + PkMachineContext ctx; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(!OCCHW_IRQ_VALID(irq) || + !OCCHW_IRQ_OWNED(irq) || + !((polarity == PK_IRQ_POLARITY_ACTIVE_HIGH) || + (polarity == PK_IRQ_POLARITY_ACTIVE_LOW)) || + !((trigger == PK_IRQ_TRIGGER_LEVEL_SENSITIVE) || + (trigger == PK_IRQ_TRIGGER_EDGE_SENSITIVE)), + PK_INVALID_ARGUMENT_IRQ_SETUP); + } + + pk_critical_section_enter(&ctx); + + if (polarity == PK_IRQ_POLARITY_ACTIVE_HIGH) { + out32(OCCHW_OIEPR_OR(irq), OCCHW_IRQ_MASK32(irq)); + } else { + out32(OCCHW_OIEPR_CLR(irq), OCCHW_IRQ_MASK32(irq)); + } + + if (trigger == PK_IRQ_TRIGGER_EDGE_SENSITIVE) { + out32(OCCHW_OITR_OR(irq), OCCHW_IRQ_MASK32(irq)); + } else { + out32(OCCHW_OITR_CLR(irq), OCCHW_IRQ_MASK32(irq)); + } + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + +/// (Re)define the IRQ handler and priority for an interrupt. +/// Return values other then PK_OK (0) are errors; see \ref pk_errors +/// +/// Note that PK allows this API to be called from any context, and changes +/// to the interrupt controller are made from a critical section. +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_ARGUMENT_IRQ_HANDLER One or more arguments are +/// invalid, including an invalid \a irq, a null (0) \a handler, +/// or invalid \a priority. + +int +pk_irq_handler_set(PkIrqId irq, + PkIrqHandler handler, + void *arg) +{ + PkMachineContext ctx; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(!OCCHW_IRQ_VALID(irq) || + (handler == 0), + PK_INVALID_ARGUMENT_IRQ_HANDLER); + } + + pk_critical_section_enter(&ctx); + + __ppe42_irq_handlers[irq].handler = handler; + __ppe42_irq_handlers[irq].arg = arg; + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + + diff --git a/src/ppe/pk/gpe/gpe_scom_handler.S b/src/ppe/pk/gpe/gpe_scom_handler.S new file mode 100644 index 0000000..7edc17e --- /dev/null +++ b/src/ppe/pk/gpe/gpe_scom_handler.S @@ -0,0 +1,122 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/gpe/gpe_scom_handler.S $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file gpe_scom_handler.S +/// \brief Interrupt handler code for SCOM requests from the ppc405 +/// + + .nolist +#include "pk.h" +#include "occhw_shared_data.h" + .list + + ## This function handles requests from the ppc405 to perform a getscom + ## or putscom operation. + ## + ## The ppc405 must supply a request in the following format: + ## + ## bytes : Content + ## ------------------- + ## 0-3 : Status + ## 4-7 : cmd/address (bit 0 is r/!w bit) + ## 8-15 : data (supplied by ppc405 on writes) + ## + ## Register Usage: + ## + ## r3: SRAM base address + ## r4: SCOM address + ## r5: MSR manipulation + ## d5: SCOM data + ## + ## NOTE: getscom requires 2 IC lines and 1 DC line + ## putscom requires 3 IC lines and 1 DC line + ## Both require the same number of instructions (16) + .align 5 + .global gpe_scom_handler +gpe_scom_handler: + + ## Load the hardcoded base address of the scom request + _liwa %r3, OSD_GPE_SCOM_ADDR + + ## Load the scom address from SRAM + lwz %r4, OCCHW_SCOM_ADDR_OFFSET(%r3) + + ## Mask all SIB errors + mfmsr %r7 + _oriwa %r5, %r7, MSR_SEM + mtmsr %r5 + + ## Check bit 0 of the scom address to determine if this + ## is a getscom or a putscom request + bb0wi %r4, 0, _do_putscom #branch if bit 0 is 0 + +_do_getscom: + ## the cmd bit was set, which means we're doing a getscom. + ## need to clear the bit first. + clrbwi %r4, %r4, 0 + + ## do the getscom + lvd %d5, 0(%r4) + + ## store the data into the request in SRAM + stvd %d5, OCCHW_SCOM_DATA_OFFSET(%r3) + +_get_scom_status: + + ## status is in the MSR, copy it to the scom request in SRAM + mfmsr %r5 + stw %r5, OCCHW_SCOM_STATUS_OFFSET(%r3) + + ## clear the IPI_SCOM interrupt: + ## first, load the bit we want to clear into a register + _liwa %r3, OCCHW_IRQ_MASK32(OCCHW_IRQ_IPI_SCOM) + + ## then, store it to the OISR0_CLR address + _stwi %r3, %r4, OCB_OISR0_CLR + + ## restore the MSR as it was before we changed it + mtmsr %r7 + + ## return + blr + +_do_putscom: + + ## load data from the request + lvd %d5, OCCHW_SCOM_DATA_OFFSET(%r3) + + ## do the putscom + stvd %d5, 0(%r4) + + b _get_scom_status + + + + diff --git a/src/ppe/pk/gpe/gpe_timebase.h b/src/ppe/pk/gpe/gpe_timebase.h new file mode 100644 index 0000000..57c96ce --- /dev/null +++ b/src/ppe/pk/gpe/gpe_timebase.h @@ -0,0 +1,64 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/gpe/gpe_timebase.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __GPE_TIMEBASE_H__ +#define __GPE_TIMEBASE_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file gpe_timebase.h +/// \brief support for using the OCB 32 bit timebase register +/// +/// The OCB timebase register is a 32 bit count-up register that is shared +/// by all GPE's in the OCC complex. + +#include "pk.h" + +#ifndef __ASSEMBLER__ + +#ifdef APPCFG_USE_EXT_TIMEBASE +static inline +uint32_t pk_timebase32_get(void) +{ + return in32(OCB_OTBR); +} + +#else +//assembly function is defined in ppe42_timebase.S +uint32_t pk_timebase32_get(void); + +#endif /* APPCFG_USE_EXT_TIMEBASE */ + +#else + + .macro _pk_timebase32_get rT, rA + _lwzi \rT, \rA, OCB_OTBR + .endm +#endif /* __ASSEMBLER__ */ + +#endif /* __GPE_TIMEBASE_H__ */ diff --git a/src/ppe/pk/gpe/pk_port.h b/src/ppe/pk/gpe/pk_port.h new file mode 100644 index 0000000..89751d7 --- /dev/null +++ b/src/ppe/pk/gpe/pk_port.h @@ -0,0 +1,40 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/gpe/pk_port.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_PORT_H__ +#define __PK_PORT_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_port.h +/// \brief The top-level GPE environment header for PK. + +#define HWMACRO_GPE + +#include "ppe42.h" +#include "gpe_timebase.h" +#endif /* __PK_PORT_H__ */ diff --git a/src/ppe/pk/gpe/pkgpefiles.mk b/src/ppe/pk/gpe/pkgpefiles.mk new file mode 100644 index 0000000..34f0f1a --- /dev/null +++ b/src/ppe/pk/gpe/pkgpefiles.mk @@ -0,0 +1,57 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/gpe/pkgpefiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file pkgpefiles.mk +# +# @brief mk for including gpe object files +# +# @page ChangeLogs Change Logs +# @section pkgpefiles.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# Object Files +########################################################################## + +GPE-C-SOURCES = gpe_init.c gpe_irq_init.c +GPE-S-SOURCES = gpe_scom_handler.S + +GPE-TIMER-C-SOURCES = +GPE-TIMER-S-SOURCES = + +GPE-THREAD-C-SOURCES = +GPE-THREAD-S-SOURCES = + +GPE-ASYNC-C-SOURCES = +GPE-ASYNC-S-SOURCES = + +GPE_OBJECTS += $(GPE-C-SOURCES:.c=.o) $(GPE-S-SOURCES:.S=.o) + diff --git a/src/ppe/pk/kernel/.empty b/src/ppe/pk/kernel/.empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/pk/kernel/.empty diff --git a/src/ppe/pk/kernel/Makefile b/src/ppe/pk/kernel/Makefile new file mode 100644 index 0000000..d08930a --- /dev/null +++ b/src/ppe/pk/kernel/Makefile @@ -0,0 +1,50 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/kernel/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# This Makefile is designed to be invoked with the -I argument set to +# the location of the "pk.mk" for the build + +include img_defs.mk +include pkkernelfiles.mk + +ifeq "$(PK_TIMER_SUPPORT)" "1" +PK_OBJECTS += ${PK-TIMER-C-SOURCES:.c=.o} +endif + +ifeq "$(PK_THREAD_SUPPORT)" "1" +PK_OBJECTS += ${PK-THREAD-C-SOURCES:.c=.o} +endif + +OBJS := $(addprefix $(OBJDIR)/, $(PK_OBJECTS)) + +all: $(OBJS) + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/pk/kernel/pk.h b/src/ppe/pk/kernel/pk.h new file mode 100644 index 0000000..055d579 --- /dev/null +++ b/src/ppe/pk/kernel/pk.h @@ -0,0 +1,149 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_H__ +#define __PK_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk.h +/// \brief The combined header of the PK kernel. +/// +/// This header will be included in any C or assembler source file that +/// requires any of the PK API. All headers defined by PK and co-compiled +/// code should be protected such that they can be included without error into +/// assembly. + +#ifndef __ASSEMBLER__ +#include <stdint.h> +#include <stddef.h> +#endif /* __ASSEMBLER__ */ + +#ifndef __PK__ +#define __PK__ 1 +#endif + +/// The application environment specifies whether or not it will provide an +/// application configuration file, which must be named "pk_app_cfg.h". + +#ifndef USE_PK_APP_CFG_H +#define USE_PK_APP_CFG_H 0 +#endif + +#if USE_PK_APP_CFG_H +#include "pk_app_cfg.h" +#endif + +#include "pk_macros.h" +#include "pk_api.h" +#include "pk_port.h" +#include "pk_kernel.h" +//#include "pk_io.h" + +#ifndef __ASSEMBLER__ + +#define MIN(X, Y) \ + ({ \ + typeof (X) __x = (X); \ + typeof (Y) __y = (Y); \ + (__x < __y) ? __x : __y; }) + +#define MAX(X, Y) \ + ({ \ + typeof (X) __x = (X); \ + typeof (Y) __y = (Y); \ + (__x > __y) ? __x : __y; \ + }) + +/// \todo These don't require 32/64 bit versions, can always promote 32->64. + +#define FLOOR_LOG2_32(x) (32 - 1 - cntlz32(x)) +#define FLOOR_LOG2_64(x) (64 - 1 - cntlz64(x)) + +#define CEILING_LOG2(x) \ + ({ \ + uint64_t __x = (uint64_t)(x); \ + int __y; \ + __y = FLOOR_LOG2_64(__x); \ + if ((__x & (__x - 1)) != 0) { \ + __y++; \ + } \ + __y;}) + + +#define POW2_32(x) ((uint32_t)1 << (x)) +#define POW2_64(x) ((uint64_t)1 << (x)) + +/// Cast a pointer to another type +/// +/// This macro is necessary when casting a pointer to a longer integer type. +/// The pointer is first cast to the equivalent integer type 'unsigned long', +/// then cast to the final type. You can also use this to cast integers longer +/// than pointers back to pointers. + +#define CAST_POINTER(t, p) ((t)((unsigned long)(p))) + + +/// Create an alignment attribute. +#define ALIGNED_ATTRIBUTE(alignment) __attribute__ ((aligned (alignment))) + +/// Create a specific-section attribute +/// +/// Note that the section \a s here must be a string. Also note that data +/// specified to reside in specific sections must always be +/// initialized. Otherwise it confuses the linker which wants to put +/// uninitialized data into .bss sections. +/// +/// \code +/// +/// int foo SECTION_ATTRIBUTE(".noncacheable") = 0; +/// int bar[10] SECTION_ATTRIBUTE(".noncacheable") = {0}; +/// +/// \endcode +#define SECTION_ATTRIBUTE(s) __attribute__ ((section (s))) + +/// Create a 'used' attribute +/// +/// This is required for example to avoid "function unused" warnings when a +/// function is declared static but only referenced by inline assembler: +/// +/// \code +/// +/// static USED_ATTRIBUTE void +/// _checkstop(void* arg, PkIrqId irq, int priority) +/// { +/// PK_PANIC(VALIDATION_CHECKSTOP); +/// } +/// +/// PK_IRQ_FAST2FULL(_validationCheckstopHandler, _checkstop); +/// +/// \endcode +#define USED_ATTRIBUTE __attribute__ ((used)) + +#endif /* __ASSEMBLER__ */ + +#endif /* __PK_H__ */ diff --git a/src/ppe/pk/kernel/pk_api.h b/src/ppe/pk/kernel/pk_api.h new file mode 100644 index 0000000..add02ba --- /dev/null +++ b/src/ppe/pk/kernel/pk_api.h @@ -0,0 +1,1026 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_api.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_API_H__ +#define __PK_API_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_api.h +/// \brief Macros and declarations for the PK API. + +// Basic constants + +/// Although the number of threads is defined as a manifest constant, +/// numerous parts of the PK code assume this definition. The number of +/// supported threads _can not_ be changed simply by changing this constant. + +#define PK_THREADS 32 + +#define PK_IDLE_THREAD_PRIORITY PK_THREADS + +// Interrupt API + +#define PK_IRQ_POLARITY_ACTIVE_LOW 0 +#define PK_IRQ_POLARITY_ACTIVE_HIGH 1 + +#define PK_IRQ_TRIGGER_LEVEL_SENSITIVE 0 +#define PK_IRQ_TRIGGER_EDGE_SENSITIVE 1 + +// API return codes + +#define PK_OK 0 +#define PK_ILLEGAL_CONTEXT_THREAD_CONTEXT 0x00779002 +#define PK_ILLEGAL_CONTEXT_INTERRUPT_CONTEXT 0x00779003 +#define PK_ILLEGAL_CONTEXT_THREAD 0x00779004 +#define PK_ILLEGAL_CONTEXT_TIMER 0x00779005 +#define PK_INVALID_THREAD_AT_RESUME1 0x00779007 +#define PK_INVALID_THREAD_AT_RESUME2 0x00779008 +#define PK_INVALID_THREAD_AT_SUSPEND1 0x00779009 +#define PK_INVALID_THREAD_AT_SUSPEND2 0x0077900a +#define PK_INVALID_THREAD_AT_DELETE 0x0077900b +#define PK_INVALID_THREAD_AT_INFO 0x0077900c +#define PK_INVALID_THREAD_AT_CHANGE 0x0077900d +#define PK_INVALID_THREAD_AT_SWAP1 0x0077900e +#define PK_INVALID_THREAD_AT_SWAP2 0x0077900f +#define PK_INVALID_THREAD_AT_CREATE 0x00779010 +#define PK_INVALID_SEMAPHORE_AT_POST 0x00779011 +#define PK_INVALID_SEMAPHORE_AT_PEND 0x00779012 +#define PK_INVALID_SEMAPHORE_AT_RELEASE 0x00779013 +#define PK_INVALID_SEMAPHORE_AT_INFO 0x00779014 +#define PK_INVALID_SEMAPHORE_AT_CREATE 0x00779015 +#define PK_INVALID_TIMER_AT_SCHEDULE 0x00779016 +#define PK_INVALID_TIMER_AT_CANCEL 0x00779017 +#define PK_INVALID_TIMER_AT_INFO 0x00779018 +#define PK_INVALID_TIMER_AT_CREATE 0x00779019 +#define PK_INVALID_ARGUMENT_IRQ_SETUP 0x0077901a +#define PK_INVALID_ARGUMENT_IRQ_HANDLER 0x0077901b +#define PK_INVALID_ARGUMENT_INTERRUPT 0x00779024 +#define PK_INVALID_ARGUMENT_CONTEXT_SET 0x00779025 +#define PK_INVALID_ARGUMENT_CONTEXT_GET 0x00779026 +#define PK_INVALID_ARGUMENT_FIT 0x00779027 +#define PK_INVALID_ARGUMENT_WATCHDOG 0x00779028 +#define PK_INVALID_ARGUMENT_INIT 0x00779029 +#define PK_INVALID_ARGUMENT_SEMAPHORE 0x0077902a +#define PK_INVALID_ARGUMENT_THREAD_CHANGE 0x0077902b +#define PK_INVALID_ARGUMENT_THREAD_PRIORITY 0x0077902c +#define PK_INVALID_ARGUMENT_THREAD1 0x0077902d +#define PK_INVALID_ARGUMENT_THREAD2 0x0077902e +#define PK_INVALID_ARGUMENT_THREAD3 0x0077902f +#define PK_STACK_OVERFLOW 0x00779030 +#define PK_TIMER_ACTIVE 0x00779031 +#define PK_TIMER_NOT_ACTIVE 0x00779032 +#define PK_PRIORITY_IN_USE_AT_RESUME 0x00779033 +#define PK_PRIORITY_IN_USE_AT_CHANGE 0x00779034 +#define PK_PRIORITY_IN_USE_AT_SWAP 0x00779035 +#define PK_SEMAPHORE_OVERFLOW 0x00779036 +#define PK_SEMAPHORE_PEND_NO_WAIT 0x00779037 +#define PK_SEMAPHORE_PEND_TIMED_OUT 0x00779038 +#define PK_SEMAPHORE_PEND_WOULD_BLOCK 0x00779039 +#define PK_INVALID_DEQUE_SENTINEL 0x0077903a +#define PK_INVALID_DEQUE_ELEMENT 0x0077903b +#define PK_INVALID_OBJECT 0x0077903c + +// Kernel panics + +#define PK_NO_TIMER_SUPPORT 0x0077903d +#define PK_START_THREADS_RETURNED 0x0077903e +#define PK_UNIMPLEMENTED 0x0077903f +#define PK_SCHEDULING_INVARIANT 0x00779040 +#define PK_TIMER_HANDLER_INVARIANT 0x00779041 +#define PK_THREAD_TIMEOUT_STATE 0x00779045 + + +/// \defgroup pk_thread_states PK Thread States +/// +/// Threads are created in the state PK_THREAD_STATE_SUSPENDED_RUNNABLE. +/// When the thread is mapped it transitions to state PK_THREAD_STATE_MAPPED. +/// A mapped thread is runnable if it appears in the run queue; there is no +/// other flag or status to indicate a runnable thread. If a blocked thread +/// is suspended it goes into state PK_THREAD_STATE_SUSPENDED_BLOCKED. For +/// all threads the reason for blockage is detailed in the \a flags field of +/// the thread; See \ref pk_thread_flags. PK_THREAD_STATE_DELETED and +/// PK_THREAD_STATE_COMPLETED are effectively equivalent but named +/// individually for reporting purposes. +/// +/// \note This separation of the thread \a state and \a flags allows the use +/// of an PK semaphore as a thread barrier, as it supports a non-iterative +/// implementation of pk_semaphore_release_all() in which all threads blocked +/// on the semaphore are simultaneously inserted into the run queue with an +/// atomic operation, followed by each individual thread readjusting its flags +/// appropriately once the thread runs again. +/// +/// @{ + +#define PK_THREAD_STATE_SUSPENDED_RUNNABLE 1 +#define PK_THREAD_STATE_MAPPED 2 +#define PK_THREAD_STATE_SUSPENDED_BLOCKED 3 +#define PK_THREAD_STATE_COMPLETED 4 +#define PK_THREAD_STATE_DELETED 5 + +/// @} + + +/// \defgroup pk_thread_flags PK Thread Flags +/// +/// The \a flag field of the thread extends the information contained in the +/// \a state field; See \ref pk_thread_states. Blocked threads will show +/// PK_THREAD_FLAG_SEMAPHORE_PEND, PK_THREAD_FLAG_TIMER_PEND or both (if +/// blocked on a semaphore with timeout). The flag PK_THREAD_FLAG_TIMED_OUT +/// indicates that a thread timer timed out before the thread became +/// runnable. Currently only the semaphore-pend-with-timeout code uses this +/// flag. +/// +/// Note that a thread can be mapped and runnable (in the run queue) even +/// though PK_THREAD_FLAG_SEMAPHORE_PEND and/or PK_THREAD_FLAG_TIMER_PEND +/// are set. These flags are always cleared by the thread itself, not the code +/// that unblocks the thread. This allows the implementation of the +/// pk_semaphore_release_all() as explained in \ref pk_thread_states. +/// +/// @{ + +#define PK_THREAD_FLAG_SEMAPHORE_PEND 0x1 +#define PK_THREAD_FLAG_TIMER_PEND 0x2 +#define PK_THREAD_FLAG_TIMED_OUT 0x4 + +/// @} + + +// Critical Sections + +/// Enter a critical section, saving the current machine +/// context. + +#define pk_critical_section_enter(pctx) \ + pk_interrupt_disable(pctx) + +/// Exit a critical section by restoring the previous machine context. + +#define pk_critical_section_exit(pctx) \ + pk_machine_context_set(pctx) + + +/// Execute a statement atomically + +#define PK_ATOMIC(stmt) \ + do { \ + PkMachineContext __ctx; \ + pk_critical_section_enter(&__ctx); \ + stmt; \ + pk_critical_section_exit(&__ctx); \ + } while (0) + + +// Application-overrideable definitions + +/// Control whether or not the API functions check for errors. +/// +/// This definition can be overriden by the application. + +#ifndef PK_ERROR_CHECK_API +#define PK_ERROR_CHECK_API 1 +#endif + +/// Control whether API errors cause kernel panics or return negative error +/// codes. +/// +/// This selection is only valid if \c PK_ERROR_CHECK_API is defined +/// non-0. This definition can be overriden by the application. + +#ifndef PK_ERROR_PANIC +#define PK_ERROR_PANIC 1 +#endif + +/// Control whether or not the PK kernel checks key invariants. +/// +/// Violations of kernel invariants always cause kernel panics. This +/// definition can be overriden by the application. + +#ifndef PK_ERROR_CHECK_KERNEL +#define PK_ERROR_CHECK_KERNEL 1 +#endif + +/// Define the time interval type, which must be an unsigned type of a size +/// less then or equal to the size of \c PkTimebase. This definition can be +/// overridden by the application. + +#ifndef PK_TIME_INTERVAL_TYPE +#define PK_TIME_INTERVAL_TYPE uint32_t +#endif + +/// Provide support for the PkTimer APIs in addition to the default +/// initerrupt APIs. This definition can be overridden by the application. + +#ifndef PK_TIMER_SUPPORT +#define PK_TIMER_SUPPORT 1 +#endif + +/// Provide support for the all PK APIs. Thread support requires/implies +/// support for time services and semaphores. This definition can be +/// overridden by the application. + +#ifndef PK_THREAD_SUPPORT +#define PK_THREAD_SUPPORT 1 +#endif + +/// Control the level of stack checking. +/// +/// This definition can be overriden by the application. +/// +/// 0 : No stack prepatterning or checking is made for thread and kernel +/// stacks. +/// +/// 1 : Kernel interrupt stacks are prepatterned during +/// \c pk_initialize(). Thread stacks are prepatterned during +/// \c pk_thread_create(). +/// +/// 2 : (\b Default - Currently Unimplemented) In addition to prepatterning, +/// stack utilization is computed at the exit of context switches and +/// interrupt processing. The maximum utilization is stored in +/// the thread data structure. The kernel will panic if stack overflow is +/// detected. Stack utilization is not computed for the idle thread. + +#ifndef PK_STACK_CHECK +#define PK_STACK_CHECK 1 +#endif + +/// A hook for main() +/// +/// This hook macro is expanded in the body of __pk_main() prior to the call +/// of the application main(). The application can redefine this hook macro +/// in (or in headers referred to in) the application header +/// pk_app_cfg.h. The PK_MAIN_HOOK will run on the stack of main(). + +#ifndef PK_MAIN_HOOK +#define PK_MAIN_HOOK do {} while (0) +#endif + +/// A hook for pk_start_threads() +/// +/// This hook macro is expanded in the call-tree of pk_start_threads() before +/// threads are actually started. The application can redefine this hook +/// macro in (or in headers referred to in) the application header +/// pk_app_cfg.h. +/// +/// The PK_START_THREADS_HOOK runs as a pseudo-interrupt handler on the +/// kernel stack, with external interrupts disabled. + +#ifndef PK_START_THREADS_HOOK +#define PK_START_THREADS_HOOK do {} while (0) +#endif + +/// The maximum value of the \c PkTimebase type. + +#define PK_TIMEBASE_MAX ((PkTimebase)-1) + +/// A special value that specifies that the timebase will not be reset during +/// pk_init(). + +#define PK_TIMEBASE_CONTINUES PK_TIMEBASE_MAX + +/// By convention, a timeout value indicating 'no waiting' in a call of \c +/// pk_semaphore_pend(). + +#define PK_NO_WAIT 0 + +/// By convention, a timeout value indicating 'wait forever' in a call of \c +/// pk_semaphore_pend(). + +#define PK_WAIT_FOREVER ((PkInterval)-1) + +/// The PK timebase frequency in Hz +/// +/// Earlier version of PK defined the timbase frequency as a preprocessor +/// macro. Now, the timebase frequency is specified as a parameter of the +/// pk_initialize() API. The macro remains defined for backwards +/// compatibility, however all kernel uses of the timebase frequency are now +/// optimized around the timebase parameter. + +#define PK_TIMEBASE_FREQUENCY_HZ __pk_timebase_frequency_hz + +/// This is the unscaled timebase frequency in Hz. +#ifdef APPCFG_USE_EXT_TIMEBASE +#define PK_BASE_FREQ_HZ 25000000 +#else +#define PK_BASE_FREQ_HZ 400000000 +#endif /* APPCFG_USE_EXT_TIMEBASE */ + +/// Scale a time interval to be _closer_ to what was actually requested +/// base on the actual timebase frequency. +#define PK_INTERVAL_SCALE(interval) ((interval) + ((interval) >> __pk_timebase_rshift)) + +/// Convert a time in integral seconds to a time interval - overflows are +/// ignored. The application can redefine this macro. + +#ifndef PK_SECONDS +#define PK_SECONDS(s) ((PkInterval)(PK_BASE_FREQ_HZ * (PkInterval)(s))) +#endif + +/// Convert a time in integral milliseconds to a time interval - overflows are +/// ignored, and a frequency evenly (or closely) divisible by 1000 is +/// assumed. The application can redefine this macro. + +#ifndef PK_MILLISECONDS +#define PK_MILLISECONDS(m) ((PkInterval)((PK_BASE_FREQ_HZ * (PkInterval)(m)) / 1000)) +#endif + +/// Convert a time in integral microseconds to a time interval - overflows are +/// ignored, and a frequncy evenly (or closely) divisible by 1,000,000 is +/// assumed. The application can redefine this macro. + +#ifndef PK_MICROSECONDS +#define PK_MICROSECONDS(u) ((PkInterval)((PK_BASE_FREQ_HZ * (PkInterval)(u)) / 1000000)) +#endif + +/// Convert a time in integral nanoseconds to a time interval - overflows are +/// ignored, and a frequeyncy evenly (or closely) divisible by 1,000,000 is +/// assumed. The application can redefine this macro. + +#ifndef PK_NANOSECONDS +#define PK_NANOSECONDS(n) ((PkInterval)((PK_BASE_FREQ_HZ * (PkInterval)(n)) / 1000000000)) +#endif + + +/// Enable PK application tracing (enabled by default) +#ifndef PK_TRACE_ENABLE +#define PK_TRACE_ENABLE 1 +#endif + +/// Enable PK kernel tracing (disabled by default) +#ifndef PK_KERNEL_TRACE_ENABLE +#define PK_KERNEL_TRACE_ENABLE 0 +#endif + +//Application trace macros +#if !PK_TRACE_ENABLE +#define PK_TRACE(...) +#define PK_TRACE_BIN(str, bufp, buf_size) +#else +#define PK_TRACE(...) PKTRACE(__VA_ARGS__) +#define PK_TRACE_BIN(str, bufp, buf_size) PKTRACE_BIN(str, bufp, buf_size) +#endif + + +//Kernel trace macros +#if !PK_KERNEL_TRACE_ENABLE +#define PK_KERN_TRACE(...) +#define PK_KERN_TRACE_ASM16(...) +#else +#define PK_KERN_TRACE(...) PK_TRACE(__VA_ARGS__) +#define PK_KERN_TRACE_ASM16(...) PK_TRACE_ASM16(__VA_ARGS__) +#endif /* PK_KERNEL_TRACE_ENABLE */ + + +/// Add a string to the trace buffer with an optional register holding a 16bit value +/// WARNING: This calls a c function which may clobber any of the volatile registers +#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) +#define PK_TRACE_ASM16(...) TRACE_ASM_HELPER16(VARG_COUNT(__VA_ARGS__), __VA_ARGS__) +#else +#define PK_TRACE_ASM16(...) +#endif /* PK_TRACE_SUPPORT */ + +/// The following macros are helper macros for tracing. They should not be called +/// directly. +#define VARG_COUNT_HELPER(_0, _1, _2, _3, _4, _5, _6, _7, N, ...) N +#define VARG_COUNT(...) VARG_COUNT_HELPER(, ##__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0) + +#ifdef __ASSEMBLER__ +#define TRACE_ASM_HELPER16_CALL(count, ...) TINY_TRACE_ASM ## count (__VA_ARGS__) +#define TRACE_ASM_HELPER16(count, ...) TRACE_ASM_HELPER16_CALL(count, __VA_ARGS__) + +#define TINY_TRACE_ASM0() .error "format string required" +#define TINY_TRACE_ASM1(str) \ + .tiny_trace_asm1 trace_ppe_hash(str, PK_TRACE_HASH_PREFIX) +#define TINY_TRACE_ASM2(str, reg) \ + .tiny_trace_asm2 trace_ppe_hash(str, PK_TRACE_HASH_PREFIX), reg +#define TINY_TRACE_ASM3() .error "too many parameters" +#define TINY_TRACE_ASM4() .error "too many parameters" +#define TINY_TRACE_ASM5() .error "too many parameters" +#define TINY_TRACE_ASM6() .error "too many parameters" +#define TINY_TRACE_ASM7() .error "too many parameters" + +//TODO: add support for tracing more than 1 parameter and binary data in assembly + + .global pk_trace_tiny + + .macro .tiny_trace_asm1 hash16 + lis %r3, \hash16 + bl pk_trace_tiny + .endm + + .macro .tiny_trace_asm2 hash16, parm16 + clrlwi %r3, \parm16, 16 + oris %r3, %r3, \hash16 + bl pk_trace_tiny + .endm + +#endif /*__ASSEMBLER__*/ + + + +#ifndef __ASSEMBLER__ + +#include <stddef.h> +#include <stdint.h> + +/// The timebase frequency in Hz; A parameter to pk_initialize() +extern uint32_t __pk_timebase_frequency_hz; + +extern uint8_t __pk_timebase_rshift; + +/// The timebase frequency in KHz +extern uint32_t __pk_timebase_frequency_khz; + +/// The timebase frequency in Mhz +extern uint32_t __pk_timebase_frequency_mhz; + + +typedef unsigned long int PkAddress; + +typedef uint8_t PkThreadState; + +typedef uint8_t PkThreadPriority; + +typedef uint8_t PkThreadFlags; + +typedef uint32_t PkSemaphoreCount; + +typedef uint64_t PkTimebase; + +typedef PK_TIME_INTERVAL_TYPE PkInterval; + +#include "pk_port_types.h" + +typedef struct { + + /// A priority queue of threads pending on the semaphore. + PkThreadQueue pending_threads; + + /// The current semaphore count. + PkSemaphoreCount count; + + /// The maximum allowable count - for error checking. + PkSemaphoreCount max_count; + +} PkSemaphore; + + +/// Compile-time initialize a PkSemaphore structure +/// +/// This low-level macro creates a structure initializatin of an PkSemaphore +/// structure. This can be used for example to create compile-time initialized +/// arrays of semaphores. +#define PK_SEMAPHORE_INITIALIZATION(_initial_count, _max_count) \ + {.pending_threads = 0, \ + .count = (_initial_count), \ + .max_count = (_max_count)} + + +/// Declare and initialize a semaphore +#define PK_SEMAPHORE(sem, initial_count, max_count) \ + PkSemaphore sem = PK_SEMAPHORE_INITIALIZATION(initial_count, max_count) + + +/// Trace macros for C functions +#define HASH_ARG_COMBO(str, arg) \ + ((((uint32_t)trace_ppe_hash(str, PK_TRACE_HASH_PREFIX)) << 16) | ((uint32_t)(arg) & 0x0000ffff)) + +#define PKTRACE0(...) pk_trace_tiny() //will fail at compile time + +#define PKTRACE1(str) \ + pk_trace_tiny((trace_ppe_hash(str, PK_TRACE_HASH_PREFIX) << 16)) + +#define PKTRACE2(str, parm0) \ + ((sizeof(parm0) <= 2)? \ + pk_trace_tiny(HASH_ARG_COMBO(str, parm0)): \ + pk_trace_big(HASH_ARG_COMBO(str, 1), ((uint64_t)parm0) << 32, 0)) + +#define PKTRACE3(str, parm0, parm1) \ + pk_trace_big(HASH_ARG_COMBO(str, 2), ((((uint64_t)parm0) << 32) | parm1), 0) + +#define PKTRACE4(str, parm0, parm1, parm2) \ + pk_trace_big(HASH_ARG_COMBO(str, 3), ((((uint64_t)parm0) << 32) | parm1),\ + ((uint64_t)parm2) << 32 ) + +#define PKTRACE5(str, parm0, parm1, parm2, parm3) \ + pk_trace_big(HASH_ARG_COMBO(str, 4), ((((uint64_t)parm0) << 32) | parm1),\ + ((((uint64_t)parm2) << 32) | parm3) ) + +#define PKTRACE6(...) pk_trace_tiny() //will fail at compile time +#define PKTRACE7(...) pk_trace_tiny() //will fail at compile time + +#define PKTRACE_HELPER2(count, ...) PKTRACE ## count (__VA_ARGS__) +#define PKTRACE_HELPER(count, ...) PKTRACE_HELPER2(count, __VA_ARGS__) + +#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) +#define PKTRACE(...) PKTRACE_HELPER(VARG_COUNT(__VA_ARGS__), __VA_ARGS__) +#define PKTRACE_BIN(str, bufp, buf_size) \ + pk_trace_binary(((buf_size < 255)? HASH_ARG_COMBO(str, buf_size): HASH_ARG_COMBO(str, 255)), bufp) +#else +#define PKTRACE(...) +#define PKTRACE_BIN(str, bufp, buf_size) +#endif //PK_TRACE_SUPPORT + + + +/// A generic doubly-linked list object +/// +/// This object functions both as a sentinel mode for a deque as well as a +/// pointer container for elements in deques. The PK API assumes that +/// queueable structures will be defined with an PkDeque structure as the +/// initial 'data member' of the structure. This allows a pointer to a queue +/// element to be cast to a pointer to an PkDeque and vice-versa. + +typedef struct PkDeque { + + /// Pointer to the head or the next element in a deque. + /// + /// When an PkDeque is used as the sentinel node for a queue, \a next + /// points to the head of the queue, and the condition (next == \<self\>) + /// indicates an empty PkDeque. By convention the condition (\a next == + /// 0) is used to indicate that a queue element is not enqueued. + struct PkDeque* next; + + /// Pointer to the tail or previous element in a deque. + /// + /// When a DQueue is used as the sentinel node for a queue, \a previous + /// points to the tail of the queue. + struct PkDeque* previous; + +} PkDeque; + + +typedef void (*PkTimerCallback)(void *); + +#define PK_TIMER_CALLBACK(callback) void callback(void *) + +struct PkTimer; + +/// The PK timer object + +typedef struct PkTimer { + + /// The time queue management pointers + /// + /// This pointer container is defined as the first element of the + /// structure to allow the PkTimer to be cast to an PkDeque and + /// vice-versa. + PkDeque deque; + + /// The absolute timeout of the timer. + PkTimebase timeout; + + /// The timer callback + /// + /// For PK thread timers used to implement Sleep and semaphore pend + /// timeouts this field is initialized to __pk_thread_timeout(). + PkTimerCallback callback; + + /// Private data passed to the callback. + /// + /// For PK thread timers used to implement Sleep and semaphore pend this + /// field is initialized to a pointer to the thread. + void *arg; + +} PkTimer; + + +// Threads + +typedef void (*PkThreadRoutine)(void *arg); + +#define PK_THREAD_ROUTINE(f) void f(void *arg); + +typedef struct { + + /// Stack pointer saved during context switches. Assembler code expects + /// this to always be at address offset 0 from the thread pointer. + PkAddress saved_stack_pointer; + + /// This is 1 past the last valid byte address of the thread stack. + /// Assembler code expects this to always be at address offset (sizeof + /// PkAddress) from the thread pointer. + PkAddress stack_limit; + + /// This is the original base of the stack. + /// Assembler code expects this to always be at address offset 2 * (sizeof + /// PkAddress) from the thread pointer. + PkAddress stack_base; + + /// If the thread is blocked on a semaphore, then this is the semaphore the + /// thread is blocked on. + PkSemaphore *semaphore; + + /// The thread priority. + PkThreadPriority priority; + + /// The thread state; See \ref pk_thread_states + PkThreadState state; + + /// Thread flags; See \ref pk_thread_flags + PkThreadFlags flags; + + /// The timer structure handles Sleep and blocking on a semaphore with + /// timeout. + PkTimer timer; + +} PkThread; + + +typedef void (*PkBhHandler)(void *); + +#define PK_BH_HANDLER(handler) void handler(void *) + +typedef struct { + + /// The bottom half queue management pointers + /// + /// This pointer container is defined as the first element of the + /// structure to allow the PkBottomHalf to be cast to a PkDeque and + /// vice-versa. + PkDeque deque; + + /// The bottom half handler + PkBhHandler bh_handler; + + /// Private data passed to the handler. + void *arg; + +} PkBottomHalf; + + +// Initialization APIs + +int +pk_initialize(PkAddress kernel_stack, + size_t kernel_stack_size, + PkTimebase initial_timebase, + uint32_t timebase_frequency_hz); + + +// Timebase APIs + +PkTimebase +pk_timebase_get(void); + + +// Timer APIs + +int +pk_timer_create(PkTimer *timer, + PkTimerCallback callback, + void *arg); + + +int +pk_timer_schedule(PkTimer *timer, + PkInterval interval); + +int +pk_timer_cancel(PkTimer *timer); + +int +pk_timer_info_get(PkTimer *timer, + PkTimebase *timeout, + int *active); + +// Thread APIs + +int +pk_thread_create(PkThread *thread, + PkThreadRoutine thread_routine, + void *arg, + PkAddress stack, + size_t stack_size, + PkThreadPriority priority); + +int +pk_start_threads(void); + +int +pk_thread_resume(PkThread *thread); + +int +pk_thread_suspend(PkThread *thread); + +int +pk_thread_delete(PkThread *thread); + +int +pk_complete(void); + +int +pk_sleep(PkInterval interval); + +int +pk_thread_info_get(PkThread *thread, + PkThreadState *state, + PkThreadPriority *priority, + int *runnable); + +int +pk_thread_priority_change(PkThread *thread, + PkThreadPriority new_priority, + PkThreadPriority *old_priority); + +int +pk_thread_at_priority(PkThreadPriority priority, + PkThread **thread); + +int +pk_thread_priority_swap(PkThread* thread_a, PkThread* thread_b); + + +// Semaphore APIs + +int +pk_semaphore_create(PkSemaphore *semaphore, + PkSemaphoreCount initial_count, + PkSemaphoreCount max_count); + +int +pk_semaphore_post(PkSemaphore *semaphore); + +int +pk_semaphore_pend(PkSemaphore *semaphore, + PkInterval timeout); + +int +pk_semaphore_release_all(PkSemaphore *semaphore); + + +int +pk_semaphore_info_get(PkSemaphore *semaphore, + PkSemaphoreCount *count, + int *pending); + +void +pk_semaphore_post_handler(void *arg, + PkIrqId irq); + +// Misc. APIs + +void +pk_halt() __attribute__ ((noreturn)); + +// Deque APIs + +int +pk_deque_sentinel_create(PkDeque *deque); + +#define PK_DEQUE_SENTINEL_INIT(dq_addr) \ +{\ + .next = dq_addr, \ + .previous = dq_addr \ +} + +#define PK_DEQUE_SENTINEL_STATIC_CREATE(deque) \ + PkDeque deque = PK_DEQUE_SENTINEL_INIT(&deque) + +int +pk_deque_element_create(PkDeque *element); + +#define PK_DEQUE_ELEMENT_INIT() \ +{\ + .next = 0, \ + .previous = 0 \ +} + +#define PK_DEQUE_ELEMENT_STATIC_CREATE(deque) \ + PkDeque deque = PK_DEQUE_ELEMENT_INIT() + +/// Check for an empty PkDeque +/// +/// \param deque The sentinel node of a deque +/// +/// \retval 0 The PkDeque is not empty +/// +/// \retval 1 The PkDeque is empty + +static inline int +pk_deque_is_empty(PkDeque *deque) +{ + return (deque == deque->next); +} + + +/// Check if an PkDeque element is currently enqueued +/// +/// \param element Typically the PkDeque object of a queable structure +/// +/// \retval 0 The element is not currently enqueued +/// +/// \retval 1 The element is currently enqueued + +static inline int +pk_deque_is_queued(PkDeque *element) +{ + return (element->next != 0); +} + + +/// Append an element to the tail of a deque (FIFO order) +/// +/// \param deque The sentinel node of a deque +/// +/// \param element Typically the PkDeque object of a queable structure +/// +/// It is an error to call this API on an element that is already enqueued, +/// but the API does not check for this error. + +static inline void +pk_deque_push_back(PkDeque *deque, PkDeque *element) +{ + deque->previous->next = element; + element->previous = deque->previous; + element->next = deque; + deque->previous = element; +} + + +/// Push an element at the head of a deque (LIFO order) +/// +/// \param deque The sentinel node of a deque +/// +/// \param element Typically the PkDeque object of a queable structure +/// +/// It is an error to call this API on an element that is already enqueued, +/// but the API does not check for this error. + +static inline void +pk_deque_push_front(PkDeque *deque, PkDeque *element) +{ + deque->next->previous = element; + element->next = deque->next; + element->previous = deque; + deque->next = element; +} + +/// Pop an element from the head of a deque +/// +/// \param deque The sentinel node of a deque +/// +/// \retval 0 The PkDeque was empty prior to the call +/// +/// \retval non-0 A pointer to the previous head of the deque, which has been +/// removed from the deque and marked as no longer queued. + +// The cast of 'head' is used to remove the 'volatile' attribute. + +static inline PkDeque * +pk_deque_pop_front(PkDeque *deque) +{ + PkDeque *head; + + if (pk_deque_is_empty(deque)) { + return 0; + } else { + head = (PkDeque *)(deque->next); + deque->next = head->next; + deque->next->previous = deque; + head->next = 0; + return head; + } +} + + +/// Remove a deque element from any position in the deque +/// +/// \param element Typically the PkDeque object of a queable structure +/// +/// It is an error to call this API on an element that is not currently +/// enqueued, but the API does not check for this error. + +static inline void +pk_deque_delete(PkDeque *element) +{ + element->previous->next = element->next; + element->next->previous = element->previous; + element->next = 0; +} + +// Bottom Half APIs + +extern PkDeque _pk_bh_queue; + +static inline void +pk_bh_schedule(PkBottomHalf *bottom_half) +{ + pk_deque_push_back(&_pk_bh_queue, (PkDeque *)bottom_half); +} + +#define PK_BH_INIT(_handler, _arg) \ +{\ + .deque = PK_DEQUE_ELEMENT_INIT(), \ + .bh_handler = _handler, \ + .arg = _arg \ +} + +#define PK_BH_STATIC_CREATE(bh_name, handler, arg) \ +PkBottomHalf bh_name = PK_BH_INIT(handler, arg) + + +//Trace function prototypes +void pk_trace_tiny(uint32_t i_parm); +void pk_trace_big(uint32_t i_hash_and_count, + uint64_t i_parm1, uint64_t i_parm2); +void pk_trace_binary(uint32_t i_hash_and_size, void* bufp); +void pk_trace_set_timebase(PkTimebase timebase); + + +/// Cast a pointer to another type, in a way that won't cause warnings + +#define PK_CAST_POINTER(t, p) ((t)((PkAddress)(p))) + +// Static Assert Macro for Compile time assertions. +// - This macro can be used both inside and outside of a function. +// - A value of false will cause the ASSERT to produce this error +// - This will show up on a compile fail as: +// <file>:<line> error: size of array '_static_assert' is negative +// - It would be trivial to use the macro to paste a more descriptive +// array name for each assert, but we will leave it like this for now. +#define PK_STATIC_ASSERT(cond) extern uint8_t _static_assert[(cond) ? 1 : -1] __attribute__ ((unused)) + +/// \page pk_errors PK API and Kernel Error Handling +/// +/// Error checking in the PK API consumes a significant amount of code space. +/// Approximately 20% of the object code in the PPC405 port is devoted to +/// error checking. Presumably a like amount of time overhead is also added to +/// PK API calls by this checking. +/// +/// API error checking can be disabled to save space and time in the kernel. +/// API errors can also be configured to cause kernel panics, allowing +/// applications to be coded without the overhead of error checking but still +/// providing an escape in the event of application errors or (unlikely) +/// hardware failures. The PK default is to check for API errors and kernel +/// invariants, and panic should errors occur. +/// +/// PK follows the Unix convention that a successful call of an API returns 0 +/// (PK_OK), but returns a negative code in the event of failure, or to +/// provide further information. The error codes are all defined as manifest +/// constants. +/// +/// Some negative codes returned by PK APIs are not considered errors. These +/// conditions are always checked, never cause a panic if they occur, and +/// their interpretation is always left to the application. See the detailed +/// documentation for each API for lists of error and non-error codes returned +/// by the API. +/// +/// There are three configuration options that control error handling in the +/// PK API and kernel: +/// +/// \c PK_ERROR_CHECK_API +/// +/// \arg \b 0 - No PK API error checking. APIs that potentially return error +/// codes will always return 0 (PK_OK) instead of an error code. Those +/// APIs that return negative codes that are not errors (see Table 1.5) +/// always return the negative non-error codes when appropriate. +/// +/// \arg \b 1 - (Default) All PK API errors are checked. The behavior in +/// the event of an error is defined by the configuration option +/// PK_ERROR_PANIC. +/// +/// \c PK_ERROR_CHECK_KERNEL +/// +/// \arg \b 0 - No kernel invariant error checking is done. +/// +/// \arg \b 1 - (Default) Selected kernel invariants are checked. The overhead +/// for these checks should be minimal. +/// +/// \c PK_ERROR_PANIC +/// +/// \arg \b 0 - PK API calls return negative error codes in the event of +/// errors. Note that PK kernel invariants always cause a panic if +/// violations occur. +/// +/// \arg \b 1 - (Default) In the event of errors PK APIs invoke PK_PANIC(code), +/// where code is a positive error code. Kernel invariant checks always +/// cause a panic if violations are detected. + +#endif /* __ASSEMBLER__ */ + +#endif /* __PK_API_H__ */ diff --git a/src/ppe/pk/kernel/pk_bh_core.c b/src/ppe/pk/kernel/pk_bh_core.c new file mode 100644 index 0000000..5db40af --- /dev/null +++ b/src/ppe/pk/kernel/pk_bh_core.c @@ -0,0 +1,53 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_bh_core.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_bh_core.c +/// \brief PK bottom half APIs +/// +/// The entry points in this file are considered 'core' routines that will +/// always be present at runtime in any PK application. + +#include "pk.h" + +/// Statically initialize the bottom half queue +PK_DEQUE_SENTINEL_STATIC_CREATE(_pk_bh_queue); + +void _pk_process_bh(void) +{ + PkBottomHalf *bh; + while((bh = (PkBottomHalf*)pk_deque_pop_front(&_pk_bh_queue)) != 0) + { + bh->bh_handler(bh->arg); + } + return; +} + + +#undef __PK_THREAD_CORE_C__ diff --git a/src/ppe/pk/kernel/pk_core.c b/src/ppe/pk/kernel/pk_core.c new file mode 100644 index 0000000..d22e3bd --- /dev/null +++ b/src/ppe/pk/kernel/pk_core.c @@ -0,0 +1,103 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_core.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_core.c +/// \brief Core routines for the PK kernel. +/// +/// The entry points in this file are routines that are expected to be needed +/// at runtime by all PK applications. This file also serves as a place for +/// kernel global variables to be realized. + +#define __PK_CORE_C__ + +#include "pk.h" + +#if !PK_TIMER_SUPPORT + +/// If there is no timer support, then any call of the timer interrupt handler +/// is considered a fatal error. + +void +__pk_timer_handler() +{ + PK_PANIC(PK_NO_TIMER_SUPPORT); +} + +#endif /* PK_TIMER_SUPPORT */ + + +/// Initialize an PkDeque sentinel node +/// +/// \param deque The sentinel node of the deque +/// +/// PK has no way of knowing whether the \a deque is currently in use, so +/// this API must only be called on unitialized or otherwise unused sentinel +/// nodes. +/// +/// \retval 0 success +/// +/// \retval -PK_INVALID_DEQUE_SENTINEL The \a deque pointer was null + +int +pk_deque_sentinel_create(PkDeque *deque) +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(deque == 0, PK_INVALID_DEQUE_SENTINEL); + } + + deque->next = deque->previous = deque; + return 0; +} + + +/// Initialize an PkDeque element +/// +/// \param element Typically the PkDeque object of a queable structure +/// +/// PK has no way of knowing whether the \a element is currently in use, so +/// this API must only be called on unitialized or otherwise unused deque +/// elements. +/// +/// \retval 0 success +/// +/// \retval -PK_INVALID_DEQUE_ELEMENT The \a element pointer was null + +int +pk_deque_element_create(PkDeque *element) +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(element == 0, PK_INVALID_DEQUE_ELEMENT); + } + + element->next = 0; + return 0; +} + +#undef __PK_CORE_C__ diff --git a/src/ppe/pk/kernel/pk_debug_ptrs.c b/src/ppe/pk/kernel/pk_debug_ptrs.c new file mode 100644 index 0000000..df2288b --- /dev/null +++ b/src/ppe/pk/kernel/pk_debug_ptrs.c @@ -0,0 +1,77 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_debug_ptrs.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_debug_ptrs.c +/// \brief Defines a table of pointers to important kernel debug data. +/// +/// This table is placed in a special section named .debug_ptrs which can be +/// placed at a well-known memory location for tools to find. +/// + +#include "pk.h" +#include "pk_trace.h" +#include "pk_debug_ptrs.h" + +extern PkTimebase ppe42_64bit_timebase; + +#if PK_TRACE_SUPPORT +extern PkTraceBuffer g_pk_trace_buf; +#endif + +pk_debug_ptrs_t pk_debug_ptrs SECTION_ATTRIBUTE(".debug_ptrs") = +{ + .debug_ptrs_size = sizeof(pk_debug_ptrs), + .debug_ptrs_version = PK_DEBUG_PTRS_VERSION, + +#if PK_TRACE_SUPPORT + .debug_trace_ptr = &g_pk_trace_buf, + .debug_trace_size = sizeof(g_pk_trace_buf), +#else + .debug_trace_ptr = 0, + .debug_trace_size = 0, +#endif /* PK_TRACE_SUPPORT */ + +#if PK_THREAD_SUPPORT + .debug_thread_table_ptr = &__pk_priority_map, + .debug_thread_table_size = sizeof(__pk_priority_map), + .debug_thread_runq_ptr = (void*)&__pk_run_queue, + .debug_thread_runq_size = sizeof(__pk_run_queue), +#else + .debug_thread_table_ptr = 0, + .debug_thread_table_size = 0, + .debug_thread_runq_ptr = 0, + .debug_thread_runq_size = 0, +#endif /* PK_THREAD_SUPPORT */ + + .debug_timebase_ptr = &ppe42_64bit_timebase, + .debug_timebase_size = sizeof(ppe42_64bit_timebase), + +}; + diff --git a/src/ppe/pk/kernel/pk_debug_ptrs.h b/src/ppe/pk/kernel/pk_debug_ptrs.h new file mode 100644 index 0000000..92a01c5 --- /dev/null +++ b/src/ppe/pk/kernel/pk_debug_ptrs.h @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_debug_ptrs.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_DEBUG_PTRS_H__ +#define __PK_DEBUG_PTRS_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_debug_ptrs.h +/// \brief Structure for a table of pointers to kernel debug data +/// + +#define PK_DEBUG_PTRS_VERSION 1 + +typedef struct +{ + // The size and version of this structure + unsigned short debug_ptrs_size; + unsigned short debug_ptrs_version; + + // Trace buffer location and size + void* debug_trace_ptr; + unsigned long debug_trace_size; + + // Thread table location and size + void* debug_thread_table_ptr; + unsigned long debug_thread_table_size; + + // Thread run queue location and size + void* debug_thread_runq_ptr; + unsigned long debug_thread_runq_size; + + // Emulated timebase location and size + void* debug_timebase_ptr; + unsigned long debug_timebase_size; + +} pk_debug_ptrs_t; + +#endif /*__PK_DEBUG_PTRS_H__*/ diff --git a/src/ppe/pk/kernel/pk_init.c b/src/ppe/pk/kernel/pk_init.c new file mode 100644 index 0000000..4886c53 --- /dev/null +++ b/src/ppe/pk/kernel/pk_init.c @@ -0,0 +1,220 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_init.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_init.c +/// \brief PK initialization +/// +/// The entry points in this file are initialization routines - they are never +/// needed after PK initialization and their code space could be reclaimed by +/// the application after initialization if required. + +#include "pk.h" +#include "pk_trace.h" + +uint32_t __pk_timebase_frequency_hz; + +/// The timebase frequency is passed into PK during initialization. It cannot +/// be set statically because there is a requirement to support a frequency +/// that can change from one IPL to the next. On the 405, scaling of time +/// intervals is accomplished by doing a 32x32 bit multiplication which is +/// supported by the ppc405 instruction set. PPE42 does not support 32x32 bit +/// multiplication directly and some applications can not afford to use a +/// function call to emulate the operation. Instead we scale the time +/// interval by shifting the value X bits to the right and adding it to itself. +/// This can scale the value by 2, 1.5, 1.25, 1.125, etc. +/// +/// This is the right shift value. +/// NOTE: shifting by 0 gives a 2x scale factor, shifting by 32 gives a 1x +/// scale factor. +uint8_t __pk_timebase_rshift = 32; + +void pk_set_timebase_rshift(uint32_t timebase_freq_hz) +{ + //Use 1.0 scale if less than halfway between 1.0 and 1.25 + if(timebase_freq_hz <= (PK_BASE_FREQ_HZ + (PK_BASE_FREQ_HZ >> 3))) + { + __pk_timebase_rshift = 32; + } + + //use 1.25 scale if less than halfway between 1.25 and 1.5 + else if(timebase_freq_hz <= (PK_BASE_FREQ_HZ + (PK_BASE_FREQ_HZ >> 3) + (PK_BASE_FREQ_HZ >> 2))) + { + __pk_timebase_rshift = 2; + } + //use 1.5 scale if less than halfway between 1.5 and 2.0 + else if(timebase_freq_hz <= (PK_BASE_FREQ_HZ + (PK_BASE_FREQ_HZ >> 2) + (PK_BASE_FREQ_HZ >> 1))) + { + __pk_timebase_rshift = 1; + } + //use 2.0 scale if greater than 1.5 + else + { + __pk_timebase_rshift = 0; + } +} + +/// Initialize PK. +/// +/// \param kernel_stack A stack area for interrupt and bottom-half handlers. +/// +/// \param kernel_stack_size The size (in bytes) of the stack area for +/// interrupt and bottom-half handlers. +/// +/// \param initial_timebase The initial value of the PK timebase. +/// If the argument is given as the special value \c PK_TIMEBASE_CONTINUES, then the +/// timebase is not reset. +/// +/// \param timebase_frequency_hz The frequency of the PK timebase in Hz. +/// +/// This routine \e must be called before any other PK / routines, and \e +/// should be called before any interrupts are enabled. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_ARGUMENT_INIT A stack pointer is 0 or is given +/// a 0 size. +/// +/// \retval -PK_STACK_OVERFLOW One or both stacks are not large enough to +/// support a minimum context save in the event of an interrupt. + +// Note that PK does not rely on any static initialization of dynamic +// variables. In debugging sessions using RAM-resident PK images it is +// assumed that the processor may be reset at any time, so we always need to +// reset everything at initialization. + +int +pk_initialize(PkAddress kernel_stack, + size_t kernel_stack_size, + PkTimebase initial_timebase, + uint32_t timebase_frequency_hz) +{ + int rc; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF((kernel_stack == 0) || + (kernel_stack_size == 0), + PK_INVALID_ARGUMENT_INIT); + } + + __pk_timebase_frequency_hz = timebase_frequency_hz; + + __pk_thread_machine_context_default = PK_THREAD_MACHINE_CONTEXT_DEFAULT; + + rc = __pk_stack_init(&kernel_stack, &kernel_stack_size); + if (rc) { + return rc; + } + + __pk_kernel_stack = kernel_stack; + __pk_kernel_stack_size = kernel_stack_size; + +#if PK_TIMER_SUPPORT + + // Initialize the time queue sentinel as a circular queue, set the next + // timeout and clear the cursor. + + pk_deque_sentinel_create((PkDeque*)&__pk_time_queue); + __pk_time_queue.cursor = 0; + __pk_time_queue.next_timeout = PK_TIMEBASE_MAX; + +#if PK_TRACE_SUPPORT +extern PkTimer g_pk_trace_timer; +extern PkTraceBuffer g_pk_trace_buf; + + //set the trace timebase HZ + g_pk_trace_buf.hz = timebase_frequency_hz; + + //set the shift adjustment to get us closer to the true + //timebase frequency (versus what was hardcoded) + pk_set_timebase_rshift(timebase_frequency_hz); + + if(initial_timebase != PK_TIMEBASE_CONTINUES) + { + //set the timebase ajdustment for trace synchronization + pk_trace_set_timebase(initial_timebase); + } + + // Schedule the timer that puts a 64bit timestamp in the trace buffer + // periodically. This allows us to use 32bit timestamps. + pk_timer_schedule(&g_pk_trace_timer, + PK_TRACE_TIMER_PERIOD); + +#endif /* PK_TRACE_SUPPORT */ + +#endif /* PK_TIMER_SUPPORT */ + +#if PK_THREAD_SUPPORT + + // Clear the priority map. The final entry [PK_THREADS] is for the idle + // thread. + + int i; + for (i = 0; i <= PK_THREADS; i++) { + __pk_priority_map[i] = 0; + } + + // Initialize the thread scheduler + + __pk_thread_queue_clear(&__pk_run_queue); + __pk_current_thread = 0; + __pk_next_thread = 0; + __pk_delayed_switch = 0; + +#endif /* PK_THREAD_SUPPORT */ + + return PK_OK; +} + + +/// Call the application main() +/// +/// __pk_main() is called from the bootloader. It's only purpose is to +/// provide a place for the PK_MAIN_HOOK to be called before main() is +/// called. + +void +__pk_main(int argc, char **argv) +{ + PK_MAIN_HOOK; + + int main(int argc, char **argv); + main(argc, argv); +} + + + + + + + + + diff --git a/src/ppe/pk/kernel/pk_kernel.h b/src/ppe/pk/kernel/pk_kernel.h new file mode 100644 index 0000000..82ffd29 --- /dev/null +++ b/src/ppe/pk/kernel/pk_kernel.h @@ -0,0 +1,270 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_kernel.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_KERNEL_H__ +#define __PK_KERNEL_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_kernel.h +/// \brief PK portable kernel (non-API) data and data structures +/// +/// \todo In theory, as long as the critical section entry/exit macros use GCC +/// memory barriers, we should be able to eliminate all of the 'volatile' +/// declarations in PK code. These have been added to the port, so +/// we should try it. + +#ifdef __PK_CORE_C__ +#define IF__PK_CORE_C__(x) x +#define UNLESS__PK_CORE_C__(x) +#else +#define IF__PK_CORE_C__(x) +#define UNLESS__PK_CORE_C__(x) x +#endif + +#if PK_MINIMIZE_KERNEL_CODE_SPACE +#define IF_PK_MINIMIZE_KERNEL_CODE_SPACE(x) x +#define UNLESS_PK_MINIMIZE_KERNEL_CODE_SPACE(x) +#else +#define IF_PK_MINIMIZE_KERNEL_CODE_SPACE(x) +#define UNLESS_PK_MINIMIZE_KERNEL_CODE_SPACE(x) x +#endif + + +#ifndef __ASSEMBLER__ + +/// This is the stack pointer saved when switching from a thread context to an +/// interrupt context. + +UNLESS__PK_CORE_C__(extern) +volatile +PkAddress __pk_saved_sp; + +/// The kernel stack; constant once defined by the call of +/// pk_initialize(). + +UNLESS__PK_CORE_C__(extern) +volatile +PkAddress __pk_kernel_stack; + +/// This is the run queue - the queue of mapped runnable tasks. +UNLESS__PK_CORE_C__(extern) +volatile +PkThreadQueue __pk_run_queue; + +/// This flag is set by \c __pk_schedule() if a new highest-priority thread +/// becomes runnable during an interrupt handler. The context switch will +/// take place at the end of interrupt processing, and the +/// interrupt handling code will clear the flag. + +UNLESS__PK_CORE_C__(extern) +volatile +int __pk_delayed_switch; + +/// The currently running thread, or NULL (0) to indicate the idle thread +/// +/// \a __pk_current_thread holds a pointer to the currently executing +/// thread. This pointer will be NULL (0) under the following conditions: +/// +/// - After pk_initialize() but prior to pk_start_threads() +/// +/// - After pk_start_threads(), when no threads are runnable. In this case +/// the NULL (0) value indicates that the PK idle thread is 'running'. +/// +/// - After pk_start_threads(), when the current (non-idle) thread has +/// completed or been deleted. +/// +/// If \a __pk_current_thread == 0 then there is no requirement to save any +/// register state on a context switch, either because the PK idle thread has +/// no permanent context, or because any thread context on the kernel stack is +/// associated with a deleted thread. +/// +/// If \a __pk_current_thread != 0 then \a __pk_current_thread is a pointer +/// to the currently executing thread. In an interrupt handler \a +/// pk_current_thread is a pointer to the thread whose context is saved on +/// the kernel stack. +UNLESS__PK_CORE_C__(extern) +volatile +PkThread* __pk_current_thread; + +/// The thread to switch to during the next context switch, or NULL (0). +/// +/// \a __pk_next_thread is computed by __pk_schedule(). \a +/// __pk_next_thread holds a pointer to the thread to switch to at the next +/// context switch. In a thread context the switch happens immediately if \a +/// __pk_next_thread == 0 or \a __pk_next_thread != \a __pk_current_thread. +/// In an interrupt context the check happens at the end of processing all +/// interrupts. +/// +/// \a __pk_next_thread may be NULL (0) under the following +/// conditions: +/// +/// - After pk_initialize() but prior to pk_start_threads(), assuming no +/// threads have been made runnable. +/// +/// - After pk_start_threads(), when no threads are runnable. In this case +/// the NULL (0) value indicates that the PK idle thread is the next thread +/// to 'run'. +/// +/// If \a __pk_next_thread == 0 then there is no requirement to restore +/// any register state on a context switch, because the PK idle thread has +/// no permanent context. +/// +/// If \a __pk_next_thread != 0 then \a __pk_next_thread is a pointer +/// to the thread whose context will be restored at the next context switch. +UNLESS__PK_CORE_C__(extern) +volatile +PkThread* __pk_next_thread; + +/// The priority of \a __pk_next_thread +/// +/// If \a __pk_next_thread == 0, the \a __pk_next_priority == PK_THREADS. +UNLESS__PK_CORE_C__(extern) +volatile +PkThreadPriority __pk_next_priority; + +/// This variable holds the default thread machine context for newly created +/// threads. The idle thread also uses this context. This variable is normally +/// constant after the call of \c pk_initialize(). + +UNLESS__PK_CORE_C__(extern) +volatile +PkMachineContext __pk_thread_machine_context_default; + + +/// The size of the kernel stack (bytes). + +UNLESS__PK_CORE_C__(extern) +volatile +size_t __pk_kernel_stack_size; + +/// This table maps priorities to threads, and contains PK_THREADS + 1 +/// entries. The final entry is for the idle thread and will always be null +/// after initizlization. + +UNLESS__PK_CORE_C__(extern) +volatile +PkThread* __pk_priority_map[PK_THREADS + 1]; + +/// The PK time queue structure +/// +/// This structure is defined for use by the kernel, however applications +/// could also use this structure to define their own time queues. + +typedef struct { + + /// A sentinel node for the time queue. + /// + /// The time queue is an PkDeque managed as a FIFO queue for queue + /// management purpose, although events time out in time order. + /// + /// This pointer container is defined as the first element of the + /// structure to allow the PkTimeQueue to be cast to an PkDeque. + PkDeque queue; + + /// The next timeout in absolute time. + PkTimebase next_timeout; + + /// A pointer to allow preemption of time queue processing + /// + /// If non-0, then this is the next timer in the time queue to handle, or + /// a pointer to the \a queue object indicating no more timers to handle. + /// + /// \a cursor != 0 implies that time queue handler is in the midst of + /// processing the time queue, but has enabled interrupt preemption for + /// processing a timer handler. This means that 1) if the timer pointed to + /// by \a cursor is deleted then the cursor must be assigned to the + /// next timer in the queue; and 2) if a new timer is scheduled then + /// activating the next timeout will be handled by the timer handler. + PkDeque* cursor; + +} PkTimeQueue; + +UNLESS__PK_CORE_C__(extern) +PkTimeQueue __pk_time_queue; + +/// Return a pointer to the PkThread object of the currently running thread, +/// or NULL (0) if PK is idle or has not been started. +/// +/// In this API the current thread is not volatile - it will never change +/// inside application code - thus the 'volatile' is cast away. The PK kernel +/// does not (must not) use this API. + +UNLESS__PK_CORE_C__(extern) +inline PkThread * +pk_current(void) +{ + return (PkThread *)__pk_current_thread; +} + +/// Schedule the next timeout in a machine-specific way. + +void +__pk_schedule_hardware_timeout(PkTimebase timeout); + +/// The thread timeout handler. Portable. + +PK_TIMER_CALLBACK(__pk_thread_timeout); + +/// Generic stack initialization. Portable. + +int +__pk_stack_init(PkAddress *stack, + size_t *size); + +/// Machine-specific thread context initialization. + +void +__pk_thread_context_initialize(PkThread *thread, + PkThreadRoutine thread_routine, + void *arg); + +/// Machine specific resumption of __pk_next_thread at __pk_next_priority +/// without saving the current context. +void +__pk_next_thread_resume(void); + +/// Schedule a timer in the time queue. Portable. +void +__pk_timer_schedule(PkTimer *timer); + +/// Remove a timer from the time queue. Portable. +int +__pk_timer_cancel(PkTimer *timer); + +void +__pk_schedule(void); + + +// Call the application main(). Portable. + +void +__pk_main(int argc, char **argv); + +#endif /* __ASSEMBLER__ */ + +#endif /* __PK_KERNEL_H__ */ diff --git a/src/ppe/pk/kernel/pk_macros.h b/src/ppe/pk/kernel/pk_macros.h new file mode 100644 index 0000000..0bff22b --- /dev/null +++ b/src/ppe/pk/kernel/pk_macros.h @@ -0,0 +1,134 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_macros.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_MACROS_H__ +#define __PK_MACROS_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_macros.h +/// \brief Boilerplate macros for PK + +/// This macro encapsulates error handling boilerplate for code that uses the +/// PK API-type error handling, for errors that do not occur in critical +/// sections. + +#define PK_ERROR(code) \ + do { \ + if (PK_ERROR_PANIC) { \ + PK_PANIC(code); \ + } else { \ + return -(code); \ + } \ + } while (0) + + +/// This macro encapsulates error handling boilerplate in the PK API +/// functions, for errors that do not occur in critical sections. + +#define PK_ERROR_IF(condition, code) \ + do { \ + if (condition) { \ + PK_ERROR(code); \ + } \ + } while (0) + + +/// This macro encapsulates error handling boilerplate in the PK API +/// functions, for errors that do not occur in critical sections and always +/// force a kernel panic, indicating a kernel or API bug. + +#define PK_PANIC_IF(condition, code) \ + do { \ + if (condition) { \ + PK_PANIC(code); \ + } \ + } while (0) + + +/// This macro encapsulates error handling boilerplate in the PK API +/// functions, for errors that do not occur in critical sections. +/// The error handling will only be enabled when PK_ERROR_CHECK_API +/// is enabled. + +#define PK_ERROR_IF_CHECK_API(condition, code) \ + do { \ + if (PK_ERROR_CHECK_API) { \ + PK_ERROR_IF(condition, code); \ + } \ + } while (0) + +/// This macro encapsulates error handling boilerplate in the PK API +/// functions, for errors that occur in critical sections. + +#define PK_ERROR_IF_CRITICAL(condition, code, context) \ + do { \ + if (condition) { \ + if (PK_ERROR_PANIC) { \ + PK_PANIC(code); \ + pk_critical_section_exit(context); \ + } else { \ + pk_critical_section_exit(context); \ + return -(code); \ + } \ + } \ + } while (0) + + +/// This is a general macro for errors that require cleanup before returning +/// the error code. + +#define PK_ERROR_IF_CLEANUP(condition, code, cleanup) \ + do { \ + if (condition) { \ + if (PK_ERROR_PANIC) { \ + PK_PANIC(code); \ + cleanup; \ + } else { \ + cleanup; \ + return -(code); \ + } \ + } \ + } while (0) + + + +/// Some PK APIs can only be called from thread contexts - these are APIs +/// that threads call on 'themselves'. + +#define PK_ERROR_UNLESS_THREAD_CONTEXT() \ + PK_ERROR_IF(!__pk_kernel_context_thread(), \ + PK_ILLEGAL_CONTEXT_THREAD_CONTEXT) + + +/// Some PK APIs must be called from an interrupt context only. + +#define PK_ERROR_UNLESS_ANY_INTERRUPT_CONTEXT() \ + PK_ERROR_IF(!__pk_kernel_context_any_interrupt(), \ + PK_ILLEGAL_CONTEXT_INTERRUPT_CONTEXT) + +#endif /* __PK_MACROS_H__ */ diff --git a/src/ppe/pk/kernel/pk_semaphore_core.c b/src/ppe/pk/kernel/pk_semaphore_core.c new file mode 100644 index 0000000..fd47106 --- /dev/null +++ b/src/ppe/pk/kernel/pk_semaphore_core.c @@ -0,0 +1,342 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_semaphore_core.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_semaphore_core.c +/// \brief PK semaphore APIs +/// +/// The entry points in this file are considered 'core' routines that will +/// always be present at runtime in any PK application that enables +/// semaphores. + +#include "pk.h" + +/// Post a count to a semaphore +/// +/// \param semaphore A pointer to the semaphore +/// +/// If any thread is pending on the semaphore, the highest priority thread +/// will be made runnable and the internal count will remain 0. +/// +/// If no thread is pending on the semaphore then the internal count will be +/// incremented by 1, with overflow wrapping the internal count through 0. If +/// the \a max_count argument supplied when the semaphore was created is +/// non-zero and the new internal count is greater than the \a max_count, an +/// overflow error will be signalled. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_SEMAPHORE_AT_POST The \a semaphore is a null (0) pointer. +/// +/// \retval -PK_SEMAPHORE_OVERFLOW The \a max_count argument supplied when +/// the semaphore was created is non-zero and the new internal count is +/// greater than the \a max_count. + +int +pk_semaphore_post(PkSemaphore *semaphore) +{ + PkMachineContext ctx; + PkThreadPriority priority; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(semaphore == 0, PK_INVALID_SEMAPHORE_AT_POST); + } + + pk_critical_section_enter(&ctx); + + priority = __pk_thread_queue_min(&(semaphore->pending_threads)); + + if (priority != PK_IDLE_THREAD_PRIORITY) { + + __pk_thread_queue_delete(&(semaphore->pending_threads), priority); + __pk_thread_queue_insert(&__pk_run_queue, priority); + + PK_KERN_TRACE("THREAD_SEMAPHORE_POST(%d)", priority); + + __pk_schedule(); + + } else { + + semaphore->count++; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF((semaphore->max_count > 0) && + (semaphore->count > semaphore->max_count), + PK_SEMAPHORE_OVERFLOW); + } + } + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + +/// Pend on a semaphore with timeout +/// +/// \param semaphore A pointer to the semaphore +/// +/// \param timeout A relative timeout in PK timebase ticks, including the +/// special values PK_NO_WAIT and PK_WAIT_FOREVER +/// +/// This API is normally called from threads, and can only be successfully +/// called from interupt handlers under special conditions. +/// +/// If the internal count of the \a semaphore is non-zero, the internal count +/// is decremented by one and execution of the caller continues. +/// +/// If the internal count of the \a semaphore is zero and the \a timeout is +/// PK_NO_WAIT (0) then the call returns immediately with the informational +/// code -PK_SEMAPHORE_PEND_NO_WAIT. +/// +/// If the internal count of the \a semaphore is zero and the \a timeout is +/// non-zero then a thread will block until either a semaphore count is +/// acquired or the relative timeout expires. If this condition occurs in a +/// call from an interrupt context or before threads have been started then +/// the call will fail with the error \c -PK_SEMAPHORE_PEND_WOULD_BLOCK. +/// +/// Once timed out the thread is removed from the semaphore pending queue and +/// made runnable, and the pk_semaphore_pend() operation will fail, even if +/// the semaphore count becomes available before the thread runs again. The +/// pk_semaphore_pend() API returns the informational code +/// -PK_SEMAPHORE_PEND_TIMED_OUT in this case. +/// +/// By convention, a timeout interval equal to the maximum possible value of +/// the \c PkInterval type is taken to mean "wait forever". A thread blocked +/// on a semaphore in this mode will never time out. PK provides this +/// constant as \c PK_WAIT_FOREVER. +/// +/// Return values other than PK_OK (0) are not necessarily errors; see \ref +/// pk_errors +/// +/// The following return codes are non-error codes: +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_SEMAPHORE_PEND_NO_WAIT timeout is set to PK_NO_WAIT +/// +/// \retval -PK_SEMAPHORE_PEND_TIMED_OUT The semaphore was not acquired +/// before the timeout expired. +/// +/// The following return codes are error codes: +/// +/// \retval -PK_INVALID_SEMAPHORE_AT_PEND The \a semaphore is a null (0) +/// pointer. +/// +/// \retval -PK_SEMAPHORE_PEND_WOULD_BLOCK The call was made from an +/// interrupt context (or before threads have been started), the semaphore +/// internal count was 0 and a non-zero timeout was specified. + +// Note: Casting __pk_current_thread removes the 'volatile' attribute. + +int +pk_semaphore_pend(PkSemaphore *semaphore, + PkInterval timeout) +{ + PkMachineContext ctx; + PkThreadPriority priority; + PkThread *thread; + PkTimer *timer = 0; + PkInterval scaled_timeout = PK_INTERVAL_SCALE(timeout); + + int rc = PK_OK; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(semaphore == 0, PK_INVALID_SEMAPHORE_AT_PEND); + } + + pk_critical_section_enter(&ctx); + + if (semaphore->count != 0) { + + semaphore->count--; + + } else if (timeout == PK_NO_WAIT) { + + rc = -PK_SEMAPHORE_PEND_NO_WAIT; + + } else { + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF_CRITICAL(!__pk_kernel_context_thread(), + PK_SEMAPHORE_PEND_WOULD_BLOCK, + &ctx); + } + + thread = (PkThread *)__pk_current_thread; + priority = thread->priority; + + __pk_thread_queue_insert(&(semaphore->pending_threads), priority); + + thread->semaphore = semaphore; + thread->flags |= PK_THREAD_FLAG_SEMAPHORE_PEND; + + PK_KERN_TRACE("THREAD_SEMAPHORE_PEND(%d)", priority); + + if (timeout != PK_WAIT_FOREVER) { + timer = &(thread->timer); + timer->timeout = pk_timebase_get() + scaled_timeout; + __pk_timer_schedule(timer); + thread->flags |= PK_THREAD_FLAG_TIMER_PEND; + } + + __pk_thread_queue_delete(&__pk_run_queue, priority); + __pk_schedule(); + + thread->flags &= ~PK_THREAD_FLAG_SEMAPHORE_PEND; + + if (thread->flags & PK_THREAD_FLAG_TIMER_PEND) { + if (thread->flags & PK_THREAD_FLAG_TIMED_OUT) { + rc = -PK_SEMAPHORE_PEND_TIMED_OUT; + __pk_thread_queue_delete(&(semaphore->pending_threads), thread->priority); + } else { + __pk_timer_cancel(timer); + } + thread->flags &= + ~(PK_THREAD_FLAG_TIMER_PEND | PK_THREAD_FLAG_TIMED_OUT); + } + } + + pk_critical_section_exit(&ctx); + + return rc; +} + + +/// Release all threads blocked on a semaphore +/// +/// \param semaphore A pointer to a semaphore +/// +/// This API is provided to allow an PK semaphore to be used as a thread +/// barrier. pk_semaphore_release_all() simultaneously unblocks all threads +/// (if any) currently pending on a semaphore. A semaphore to be used as a +/// thread barrier will typically be initialized with +/// pk_semaphore_create(\a sem, 0, 0), and sxx_semaphore_post() would never be +/// called on the \a sem. +/// +/// This API never modifies the \a count field of the semaphore; If any +/// threads are blocked on a semaphore the semaphore count is 0 by definition. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_SEMAPHORE_AT_RELEASE The \a semaphore is a null (0) +/// pointer. + +int +pk_semaphore_release_all(PkSemaphore* semaphore) +{ + PkMachineContext ctx; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(semaphore == 0, PK_INVALID_SEMAPHORE_AT_RELEASE); + } + + pk_critical_section_enter(&ctx); + + __pk_thread_queue_union(&__pk_run_queue, &(semaphore->pending_threads)); + __pk_thread_queue_clear(&(semaphore->pending_threads)); + __pk_schedule(); + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + +/// Get information about a semaphore. +/// +/// \param semaphore A pointer to the PkSemaphore to query +/// +/// \param count The value returned through this pointer is the current count +/// of the semaphore. The caller can set this parameter to the null pointer +/// (0) if this information is not required. +/// +/// \param pending The value returned through this pointer is the current +/// number of threads pending on the semaphore. The caller can set this +/// parameter to the null pointer (0) if this information is not required. +/// +/// The information returned by this API can only be guaranteed consistent if +/// the API is called from a critical section. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_SEMAPHORE_AT_INFO The \a semaphore is a null (0) +/// pointer. + +int +pk_semaphore_info_get(PkSemaphore* semaphore, + PkSemaphoreCount* count, + int* pending) + +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(semaphore == 0, PK_INVALID_SEMAPHORE_AT_INFO); + } + + if (count) { + *count = semaphore->count; + } + if (pending) { + *pending = __pk_thread_queue_count(&(semaphore->pending_threads)); + } + + return PK_OK; +} + + +/// An simple interrupt handler that posts to a semaphore. +/// +/// To implement basic event-driven blocking of a thread, install +/// pk_semaphore_post_handler() as the handler for an interrupt +/// and provide a pointer to the semaphore as the \a arg argument in +/// pk_irq_handler_set(). The semaphore should be initialized with +/// pk_semaphore_create(&sem, 0, 1). This handler simply disables (masks) +/// the interrupt, clears the status and calls pk_semaphore_post() on the +/// semaphore. +/// +/// Note that clearing the status in the interrupt controller as done here is +/// effectively a no-op for level-sensitive interrupts. In the level-sensitive +/// case any thread pending on the semaphore must reset the interrupt +/// condition in the device before re-enabling the interrupt. +#if 0 +void +pk_semaphore_post_handler(void *arg, PkIrqId irq, int priority) +{ + pk_irq_disable(irq); + pk_irq_status_clear(irq); + pk_semaphore_post((PkSemaphore *)arg); +} + +#endif diff --git a/src/ppe/pk/kernel/pk_semaphore_init.c b/src/ppe/pk/kernel/pk_semaphore_init.c new file mode 100644 index 0000000..aea00f6 --- /dev/null +++ b/src/ppe/pk/kernel/pk_semaphore_init.c @@ -0,0 +1,106 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_semaphore_init.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_semaphore_init.c +/// \brief PK semaphore API initialization routines +/// +/// The entry points in this file are routines that are typically used during +/// initialization, and their code space could be deallocated and recovered if +/// no longer needed by the application after initialization. + +#include "pk.h" + +/// Create (initialize) a semaphore +/// +/// \param semaphore A pointer to an PkSemaphore structure to initialize +/// +/// \param initial_count The initial count of the semaphore +/// +/// \param max_count The maximum count allowed in the semaphore, for error +/// checking +/// +/// Semaphores are created (initialized) by a call of \c +/// pk_semaphore_create(), using an application-provided instance of an \c +/// PkSemaphore structure. This structure \e is the semaphore, so the +/// application must never modify the structure if the semaphore is in use. +/// PK has no way to know if an \c PkSemaphore structure provided to +/// \c pk_semaphore_create() is safe to use as a semaphore, and will silently +/// modify whatever memory is provided. +/// +/// PK provides two simple overflow semantics based on the value of max_count +/// in the call of \c pk_semaphore_create(). +/// +/// If \a max_count = 0, then posting to the semaphore first increments the +/// internal count by 1. Overflows are ignored and will wrap the internal +/// count through 0. +/// +/// If \a max_count != 0, then posting to the semaphore first increments the +/// internal count by 1, wrapping through 0 in the event of overflow. If the +/// resulting count is greater than max_count, \c pk_semaphore_post() will +/// return the error \c -PK_SEMAPHORE_POST_OVERFLOW to the caller. +/// +/// In most applications it is probably best to use the \a max_count != 0 +/// semantics to trap programming errors, unless there is a specific +/// application where overflow is expected and ignorable. As a fine point of +/// the specification, a \a max_count of 0 is equivalent to a max_count of +/// 0xFFFFFFFF. +/// +/// Return values other then PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_SEMAPHORE_AT_CREATE The \a semaphore is a null (0) +/// pointer. +/// +/// \retval -PK_INVALID_ARGUMENT_SEMAPHORE The \a max_count is non-zero +/// and less than the \a initial_count. + +int +pk_semaphore_create(PkSemaphore *semaphore, + PkSemaphoreCount initial_count, + PkSemaphoreCount max_count) +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(semaphore == 0, PK_INVALID_SEMAPHORE_AT_CREATE); + PK_ERROR_IF((max_count != 0) && (initial_count > max_count), + PK_INVALID_ARGUMENT_SEMAPHORE); + } + + __pk_thread_queue_clear(&(semaphore->pending_threads)); + semaphore->count = initial_count; + semaphore->max_count = max_count; + + return PK_OK; +} + + + + + diff --git a/src/ppe/pk/kernel/pk_stack_init.c b/src/ppe/pk/kernel/pk_stack_init.c new file mode 100644 index 0000000..4cfc260 --- /dev/null +++ b/src/ppe/pk/kernel/pk_stack_init.c @@ -0,0 +1,109 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_stack_init.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_stack_init.c +/// \brief PK stack initialization +/// +/// The entry points in this file are initialization routines - they are never +/// needed after PK initialization and their code space could be reclaimed by +/// the application after initialization if required. +/// +/// This code was split out from "pk_init.c" because it may be needed in a +/// thread configuration if threads are being created dynamically. in an +/// interrupt-only configuration it is not needed after \c pk_initialize(). + +#include "pk.h" + +/// Initialize a stack area. +/// +/// \param stack A pointer to the smallest legal address of the stack. The +/// stack address is modified as the stack is aligned and initialized. +/// +/// \param size A pointer to the size of the stack (in bytes). The size is +/// modified as the stack is aligned and initialized. At exit this is the +/// final usable stack area size aligned to the size of the PK_STACK_TYPE. +/// +/// PK makes no assumptions about size or alignment of the area provided as a +/// stack, and carefully aligns and initializes the stack. Regardless of how +/// the stack grows, the \a stack parameter is considered to be the lowest +/// legal address of the stack. + +int +__pk_stack_init(PkAddress *stack, + size_t *size) +{ + PkAddress mask; + size_t excess, i, count; + PK_STACK_TYPE *p; + + if (PK_STACK_DIRECTION < 0) { + + // Stacks grow down. The initial stack pointer is set to just above + // the last allocated stack address. This is legal for pre-decrement + // stacks, otherwise the initial address is first brought into range + // before alignment. The stack is aligned downward, then the size is + // adjusted to a multiple of the stack type. Stacks are optionally + // prepatterned. Alignment is assumed to be a power of 2. + + *stack += *size; + + if (!PK_STACK_PRE_DECREMENT) { + *stack -= sizeof(PK_STACK_TYPE); + *size -= sizeof(PK_STACK_TYPE); + } + + mask = PK_STACK_ALIGNMENT - 1; + excess = *stack & mask; + *stack -= excess; + *size -= excess; + *size = (*size / sizeof(PK_STACK_TYPE)) * sizeof(PK_STACK_TYPE); + + if (PK_STACK_CHECK) { + p = (PK_STACK_TYPE *)(*stack); + count = *size / sizeof(PK_STACK_TYPE); + for (i = 0; i < count; i++) { + if (PK_STACK_PRE_DECREMENT) { + *(--p) = PK_STACK_PATTERN; + } else { + *(p--) = PK_STACK_PATTERN; + } + } + } + + __pk_stack_create_initial_frame(stack, size); + + } else { + + PK_PANIC(PK_UNIMPLEMENTED); + } + + return PK_OK; +} + diff --git a/src/ppe/pk/kernel/pk_thread.h b/src/ppe/pk/kernel/pk_thread.h new file mode 100644 index 0000000..4848650 --- /dev/null +++ b/src/ppe/pk/kernel/pk_thread.h @@ -0,0 +1,80 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_thread.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_THREAD_H__ +#define __PK_THREAD_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_thread.h +/// \brief Contains private declarations and definitions needed for threads +/// + +void +__pk_thread_map(PkThread* thread); + +void +__pk_thread_unmap(PkThread *thread); + + +// Interrupts must be disabled at entry. + +static inline int +__pk_thread_is_active(PkThread *thread) +{ + return ((thread->state != PK_THREAD_STATE_COMPLETED) && + (thread->state != PK_THREAD_STATE_DELETED)); +} + + +// Interrupts must be disabled at entry. + +static inline int +__pk_thread_is_mapped(PkThread *thread) +{ + return (thread->state == PK_THREAD_STATE_MAPPED); +} + + +// Interrupts must be disabled at entry. This is only called on mapped threads. + +static inline int +__pk_thread_is_runnable(PkThread *thread) +{ + return __pk_thread_queue_member(&__pk_run_queue, thread->priority); +} + + +// Interrupts must be disabled at entry. + +static inline PkThread* +__pk_thread_at_priority(PkThreadPriority priority) +{ + return (PkThread*)__pk_priority_map[priority]; +} + +#endif /* __PK_THREAD_H__ */ diff --git a/src/ppe/pk/kernel/pk_thread_core.c b/src/ppe/pk/kernel/pk_thread_core.c new file mode 100644 index 0000000..06a2e1b --- /dev/null +++ b/src/ppe/pk/kernel/pk_thread_core.c @@ -0,0 +1,597 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_thread_core.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_thread_core.c +/// \brief PK thread APIs +/// +/// The entry points in this file are considered 'core' routines that will +/// always be present at runtime in any PK application that enables threads. + +#include "pk.h" +#include "pk_thread.h" + +#define __PK_THREAD_CORE_C__ + + +// This routine is only used locally. Interrupts must be disabled +// at entry. The caller must also have checked that the priority is free. +// This routine is only called on threads known to be in a suspended state, +// either PK_THREAD_STATE_SUSPENDED_RUNNABLE or +// PK_THREAD_STATE_SUSPENDED_BLOCKED. Mapping a runnable thread adds it to +// the run queue. Mapping a thread pending on a semaphore either takes the +// count and becomes runnable or adds the thread to the pending queue for the +// semaphore. Mapping a sleeping thread requires no further action +// here. Scheduling after the map must be handled by the caller. + +void +__pk_thread_map(PkThread* thread) +{ + PkThreadPriority priority; + + priority = thread->priority; + __pk_priority_map[priority] = thread; + + if (thread->state == PK_THREAD_STATE_SUSPENDED_RUNNABLE) { + + __pk_thread_queue_insert(&__pk_run_queue, priority); + + } else if (thread->flags & PK_THREAD_FLAG_SEMAPHORE_PEND) { + + if (thread->semaphore->count) { + + thread->semaphore->count--; + __pk_thread_queue_insert(&__pk_run_queue, priority); + + } else { + + __pk_thread_queue_insert(&(thread->semaphore->pending_threads), + priority); + } + } + + thread->state = PK_THREAD_STATE_MAPPED; + + if (PK_KERNEL_TRACE_ENABLE) { + if (__pk_thread_is_runnable(thread)) { + PK_KERN_TRACE("THREAD_MAPPED_RUNNABLE(%d)", priority); + } else if (thread->flags & PK_THREAD_FLAG_SEMAPHORE_PEND) { + PK_KERN_TRACE("THREAD_MAPPED_SEMAPHORE_PEND(%d)", priority); + } else { + PK_KERN_TRACE("THREAD_MAPPED_SLEEPING(%d)", priority); + } + } +} + + +// This routine is only used locally. Interrupts must be disabled +// at entry. This routine is only ever called on threads in the +// PK_THREAD_STATE_MAPPED. Unmapping a thread removes it from the priority +// map, the run queue and any semaphore pend, but does not cancel any +// timers. Scheduling must be handled by the code calling +// __pk_thread_unmap(). + +void +__pk_thread_unmap(PkThread *thread) +{ + PkThreadPriority priority; + + priority = thread->priority; + __pk_priority_map[priority] = 0; + + if (__pk_thread_is_runnable(thread)) { + + thread->state = PK_THREAD_STATE_SUSPENDED_RUNNABLE; + __pk_thread_queue_delete(&__pk_run_queue, priority); + + } else { + + thread->state = PK_THREAD_STATE_SUSPENDED_BLOCKED; + if (thread->flags & PK_THREAD_FLAG_SEMAPHORE_PEND) { + __pk_thread_queue_delete(&(thread->semaphore->pending_threads), + priority); + } + } +} + + +// Schedule and run the highest-priority mapped runnable thread. +// +// The priority of the next thread to run is first computed. This may be +// PK_THREADS, indicating that the only thread to run is the idle thread. +// This will always cause (or defer) a 'context switch' to the idle thread. +// Otherwise, if the new thread is not equal to the current thread this will +// also cause (or defer) a context switch. Note that scheduling is defined in +// terms of priorities but actually implemented in terms of PkThread pointers. +// +// If we are not yet in thread mode we're done - threads will be started by +// pk_start_threads() later. If we're in thread context a context switch +// happens immediately. In an interrupt context the switch is deferred to the +// end of interrupt processing. + +void +__pk_schedule(void) +{ + __pk_next_priority = __pk_thread_queue_min(&__pk_run_queue); + __pk_next_thread = __pk_priority_map[__pk_next_priority]; + + if ((__pk_next_thread == 0) || + (__pk_next_thread != __pk_current_thread)) { + + if (__pk_kernel_mode_thread()) { + if (__pk_kernel_context_thread()) { + if (__pk_current_thread != 0) { + __pk_switch(); + } else { + __pk_next_thread_resume(); + } + } else { + __pk_delayed_switch = 1; + } + } + } +} + + +// This routine is only used locally. +// +// Completion and deletion are pretty much the same thing. Completion is +// simply self-deletion of the current thread (which is mapped by +// definition.) The complete/delete APIs have slightly different error +// conditions but are otherwise the same. +// +// Deleting a mapped thread first unmaps (suspends) the thread, which takes +// care of removing the thread from any semaphores it may be pending on. Then +// any outstanding timer is also cancelled. +// +// If the current thread is being deleted we install the idle thread as +// __pk_current_thread, so scheduling is forced and no context is saved on +// the context switch. +// +// Note that we do not create trace events for unmapped threads since the trace +// tag only encodes the priority, which may be in use by a mapped thread. + +void +__pk_thread_delete(PkThread *thread, PkThreadState final_state) +{ + PkMachineContext ctx; + int mapped; + + pk_critical_section_enter(&ctx); + + mapped = __pk_thread_is_mapped(thread); + + if (mapped) { + __pk_thread_unmap(thread); + } + + __pk_timer_cancel(&(thread->timer)); + thread->state = final_state; + + if (mapped) { + + if (PK_KERNEL_TRACE_ENABLE) { + if (final_state == PK_THREAD_STATE_DELETED) { + PK_KERN_TRACE("THREAD_DELETED(%d)", thread->priority); + } else { + PK_KERN_TRACE("THREAD_COMPLETED(%d)", thread->priority); + } + } + + if (thread == __pk_current_thread) { + __pk_current_thread = 0; + } + __pk_schedule(); + } + + pk_critical_section_exit(&ctx); +} + + +// Generic thread timeout +// +// This routine is called as a timer callback either because a sleeping thread +// has timed out or a thread pending on a semaphore has timed out. If the +// thread is not already runnable then the the timeout flag is set, and if the +// thread is mapped it is scheduled. +// +// This implementation allows that a thread blocked on a timer may have been +// made runnable by some other mechanism, such as acquiring a semaphore. In +// order to provide an iteration-free implementation of +// pk_semaphore_release_all(), cancelling any semaphore timeouts is deferred +// until the thread runs again. +// +// Note that we do not create trace events for unmapped threads since the trace +// tag only encodes the priority, which may be in use by a mapped thread. + +void +__pk_thread_timeout(void *arg) +{ + PkMachineContext ctx; + PkThread *thread = (PkThread *)arg; + + pk_critical_section_enter(&ctx); + + switch (thread->state) { + + case PK_THREAD_STATE_MAPPED: + if (!__pk_thread_is_runnable(thread)) { + thread->flags |= PK_THREAD_FLAG_TIMED_OUT; + __pk_thread_queue_insert(&__pk_run_queue, thread->priority); + __pk_schedule(); + } + break; + + case PK_THREAD_STATE_SUSPENDED_RUNNABLE: + break; + + case PK_THREAD_STATE_SUSPENDED_BLOCKED: + thread->flags |= PK_THREAD_FLAG_TIMED_OUT; + thread->state = PK_THREAD_STATE_SUSPENDED_RUNNABLE; + break; + + default: + PK_PANIC(PK_THREAD_TIMEOUT_STATE); + } + + pk_critical_section_exit(&ctx); +} + + +// This routine serves as a container for the PK_START_THREADS_HOOK and +// actually starts threads. The helper routine __pk_call_pk_start_threads() +// arranges this routine to be called with interrupts disabled while running +// on the kernel stack. +// +// The reason for this roundabout is that we want to be able to run a hook +// routine (transparent to the application) that can hand over every last byte +// of free memory to "malloc()" - including the stack of main(). Since we +// always need to run on some stack, we chose to run the hook on the kernel +// stack. However to do this safely we need to make sure +// that no interrupts will happen during this time. When __pk_thread_resume() +// is finally called all stack-based context is lost but it doesn't matter at +// that point - it's a one-way street into thread execution. +// +// This is considered part of pk_start_threads() and so is also considered a +// 'core' routine. + +void +__pk_start_threads(void) +{ + PK_START_THREADS_HOOK; + + __pk_next_thread_resume(); + + PK_PANIC(PK_START_THREADS_RETURNED); +} + + +/// Start PK threads +/// +/// This routine starts the PK thread scheduler infrastructure. This routine +/// must be called after a call of \c pk_initialize(). This routine never +/// returns. Interrupt (+ timer) only configurations of PK need not call this +/// routine. +/// +/// Note: This tiny routine is considered a 'core' routine so that the +/// initialziation code can safely recover all 'init' code space before +/// starting threads. +/// +/// This routine typically does not return - any return value indicates an +/// error; see \ref pk_errors +/// +/// \retval -PK_ILLEGAL_CONTEXT_THREAD The API was called twice. + +int +pk_start_threads(void) +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(__pk_kernel_mode_thread(), PK_ILLEGAL_CONTEXT_THREAD); + } + + __pk_call_pk_start_threads(); + + return 0; +} + + +/// Resume a suspended thread +/// +/// \param thread The thread to resume +/// +/// PK only allows one thread at a time to run at a given priority, and +/// implements the notion of a thread \e claiming a priority. A suspended +/// thread claims a priority when it is mapped by a call of +/// pk_thread_resume(). This API will succeed only if no other active thread +/// is currently mapped at the priority assigned to the thread. PK provides +/// the pk_thread_at_priority() API which allows an application-level +/// scheduler to correctly manage multiple threads running at the same +/// priority. +/// +/// If the thread was sleeping while suspended it remains asleep. However if +/// the sleep timer timed out while the thread was suspended it will be +/// resumed runnable. +/// +/// If the thread was blocked on a semaphore when it was suspended, then when +/// the thread is resumed it will attempt to reacquire the semaphore. +/// However, if the thread was blocked on a semaphore with timeout while +/// suspended and the timeout interval has passed, the thread will be resumed +/// runnable and see that the semaphore pend timed out. +/// +/// It is not an error to call pk_thread_resume() on a mapped +/// thread. However it is an error to call pk_thread_resume() on a completed +/// or deleted thread. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion, including calls on a \a thread that is +/// already mapped. +/// +/// \retval -PK_INVALID_THREAD_AT_RESUME1 The \a thread is a null (0) pointer. +/// +/// \retval -PK_INVALID_THREAD_AT_RESUME2 The \a thread is not active, +/// i.e. has completed or been deleted. +/// +/// \retval -PK_PRIORITY_IN_USE_AT_RESUME Another thread is already mapped at +/// the priority of the \a thread. + +int +pk_thread_resume(PkThread *thread) +{ + PkMachineContext ctx; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(thread == 0, PK_INVALID_THREAD_AT_RESUME1); + } + + pk_critical_section_enter(&ctx); + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF_CRITICAL(!__pk_thread_is_active(thread), + PK_INVALID_THREAD_AT_RESUME2, + &ctx); + } + + if (!__pk_thread_is_mapped(thread)) { + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF_CRITICAL(__pk_priority_map[thread->priority] != 0, + PK_PRIORITY_IN_USE_AT_RESUME, + &ctx); + } + __pk_thread_map(thread); + __pk_schedule(); + } + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + +/// Suspend a thread +/// +/// Any active thread can be suspended. A suspended thread 1) remains active +/// but will not be scheduled; 2) relinquishes its priority assignment, +/// allowing another thread to be resumed at the suspended thread's priority; +/// and 3) disassociates from any semaphore mutual exclusion it may have been +/// participating in. +/// +/// If a sleeping thread is suspended, the sleep timer remains active but a +/// timeout of the timer simply marks the thread as runnable, but does not +/// resume the thread. +/// +/// If a thread blocked on a semaphore is suspended, the thread no longer +/// participates in the semaphore mutual exclusion. If the thread is later +/// resumed it will attempt to acquire the semaphore again the next time it +/// runs (unless it was blocked with a timeout and the timeout has expired). +/// +/// If a thread blocked on a semaphore with timeout is suspended, the +/// semaphore timeout timer continues to run. If the timer times out while the +/// thread is suspended the thread is simply marked runnable. If the thread is +/// later resumed, the suspended call of \c pk_semaphore_pend() will return the +/// timeout code -PK_SEMAPHORE_PEND_TIMED_OUT. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion, including calls on a \a thread that is +/// already suspended. +/// +/// \retval -PK_INVALID_THREAD_AT_SUSPEND1 The \a thread is a null (0) pointer +/// +/// \retval -PK_INVALID_THREAD_AT_SUSPEND2 The \a thread is not active, +/// i.e. has completed or been deleted. + +int +pk_thread_suspend(PkThread *thread) +{ + PkMachineContext ctx; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF((thread == 0), PK_INVALID_THREAD_AT_SUSPEND1); + } + + pk_critical_section_enter(&ctx); + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF_CRITICAL(!__pk_thread_is_active(thread), + PK_INVALID_THREAD_AT_SUSPEND2, + &ctx); + } + + if (__pk_thread_is_mapped(thread)) { + + PK_KERN_TRACE("THREAD_SUSPENDED(%d)", thread->priority); + __pk_thread_unmap(thread); + __pk_schedule(); + } + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + +/// Delete a thread +/// +/// Any active thread can be deleted. If a thread is deleted it is removed +/// from the run queue, deleted from the timer queue (if sleeping or blocked +/// on a semaphore with timeout), and deleted from the semaphore mutual +/// exclusion if blocked on a semaphore. The thread control block is then +/// marked as deleted. +/// +/// Once a thread has completed or been deleted the thread structure and +/// thread stack areas can be used for other purposes. +/// +/// \param thread The thread to delete +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors. If a +/// thread deletes itself this API does not return at all. +/// +/// \retval 0 Successful completion, including calls on a \a thread that has +/// completed or had already been deleted. +/// +/// +/// \retval -PK_INVALID_THREAD_AT_DELETE The \a thread is a null (0) pointer. + +int +pk_thread_delete(PkThread *thread) +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(thread == 0, PK_INVALID_THREAD_AT_DELETE); + } + + __pk_thread_delete(thread, PK_THREAD_STATE_DELETED); + + return PK_OK; +} + + +/// Complete a thread +/// +/// If a thread ever returns from the subroutine defining the thread entry +/// point, the thread is removed from all PK kernel data structures and +/// marked completed. The thread routine can also use the API pk_complete() +/// to make this more explicit if desired. PK makes no distinction between +/// completed and deleted threads, but provides these indications for +/// the benefit of the application. +/// +/// Note that this API is only available from the current thread to mark its +/// own completion. +/// +/// Once a thread has completed or been deleted the thread structure and +/// thread stack areas can be used for other purposes. +/// +/// Any return value indicates an error; see \ref pk_errors. In the event of +/// a successful completion this API does not return to the caller, which is +/// always the thread context being completed. +/// +/// \retval -PK_ILLEGAL_CONTEXT_THREAD The API was not called from a thread +/// context. + +// Note: Casting __pk_current_thread removes the 'volatile' attribute. + +int +pk_complete(void) +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_UNLESS_THREAD_CONTEXT(); + } + + __pk_thread_delete((PkThread *)__pk_current_thread, + PK_THREAD_STATE_COMPLETED); + + return PK_OK; +} + +/// Sleep a thread for an interval relative to the current time. +/// +/// \param interval A time interval relative to the current timebase. +/// +/// Threads can use this API to sleep for a time relative to the current +/// timebase. The absolute timeout is \c pk_timebase_get() + \a interval. +/// +/// Sleeping threads are not scheduled, although they maintain their +/// priorities. This differs from thread suspension, where the suspended +/// thread relinquishes its priority. When the sleep timer times out the +/// thread becomes runnable again, and will run as soon as it becomes the +/// highest-priority mapped runnable thread. +/// +/// Sleeping threads may also be later suspended. In this case the Sleep timer +/// continues to run, and if it times out before the thread is resumed the +/// thread will be immediately runnable when it is resumed. +/// +/// See the PK specification for a full discussion of how PK handles +/// scheduling events at absolute times "in the past". Briefly stated, if the +/// \a interval is 0 or is so small that the absolute time becomes a "past" +/// time before the Sleep is actually scheduled, the thread will Sleep for the +/// briefest possible period supported by the hardware. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion. +/// +/// \retval -PK_ILLEGAL_CONTEXT_THREAD The API was not called from a thread +/// context. + +int +pk_sleep(PkInterval interval) +{ + PkTimebase time; + PkMachineContext ctx; + PkThread *current; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_UNLESS_THREAD_CONTEXT(); + } + + time = pk_timebase_get() + PK_INTERVAL_SCALE(interval); + + pk_critical_section_enter(&ctx); + + current = (PkThread *)__pk_current_thread; + + current->timer.timeout = time; + __pk_timer_schedule(&(current->timer)); + + current->flags |= PK_THREAD_FLAG_TIMER_PEND; + + PK_KERN_TRACE("THREAD_SLEEP(%d)", current->priority); + + __pk_thread_queue_delete(&__pk_run_queue, current->priority); + __pk_schedule(); + + current->flags &= ~(PK_THREAD_FLAG_TIMER_PEND | PK_THREAD_FLAG_TIMED_OUT); + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + +#undef __PK_THREAD_CORE_C__ diff --git a/src/ppe/pk/kernel/pk_thread_init.c b/src/ppe/pk/kernel/pk_thread_init.c new file mode 100644 index 0000000..b2c7735 --- /dev/null +++ b/src/ppe/pk/kernel/pk_thread_init.c @@ -0,0 +1,158 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_thread_init.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_thread_init.c +/// \brief PK thread API initialization routines +/// +/// The entry points in this file are routines that are typically used during +/// initialization, and their code space could be deallocated and recovered if +/// no longer needed by the application after initialization. + +#include "pk.h" + +/// Create (initialize) a thread +/// +/// \param thread A pointer to an PkThread structure to initialize +/// +/// \param thread_routine The subroutine that implements the thread +/// +/// \param arg Private data to be passed as the argument to the thread +/// routine when it begins execution +/// +/// \param stack The stack space of the thread +/// +/// \param stack_size The size of the stack in bytes +/// +/// \param priority The initial priority of the thread +/// +/// The \a thread argument must be a pointer to an uninitialized or completed +/// or deleted thread. This \c PkThread structure \em is the thread, so this +/// memory area must not be modified by the application until the thread +/// completes or is deleted. PK can not tell if an PkThread structure is +/// currently in use as a thread control block.pk_thread_create() will +/// silently overwrite an PkThread structure that is currently in use. +/// +/// The stack area must be large enough to hold the dynamic stack requirements +/// of the entry point routine, and all subroutines and functions that might +/// be invoked on any path from the entry point. The stack must also always +/// be able to hold the thread context in the event the thread is preempted, +/// plus other critical context. PK aligns stack areas in machine-specific +/// ways, so that the actual stack area may reduced in size slightly if it is +/// not already aligned. +/// +/// Threads are created runnable but unmapped. A newly created thread will +/// not be eligible to run until a call of pk_thread_resume() targets the +/// thread. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_THREAD_AT_CREATE The \a thread is a null (0) pointer. +/// +/// \retval -PK_INVALID_ARGUMENT_THREAD1 the \a thread_routine is null (0) +/// +/// \retval -PK_INVALID_ARGUMENT_THREAD2 the \a priority is invalid, +/// +/// \retval -PK_INVALID_ARGUMENT_THREAD3 the stack area wraps around +/// the end of memory. +/// +/// \retval -PK_STACK_OVERFLOW The stack area at thread creation is smaller +/// than the minimum safe size. + +int +pk_thread_create(PkThread *thread, + PkThreadRoutine thread_routine, + void *arg, + PkAddress stack, + size_t stack_size, + PkThreadPriority priority) +{ + int rc; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(thread == 0, PK_INVALID_THREAD_AT_CREATE); + PK_ERROR_IF((thread_routine == 0) || + (priority >= PK_THREADS), + PK_INVALID_ARGUMENT_THREAD1); + } + + rc = __pk_stack_init(&stack, &stack_size); + if (rc) { + return rc; + } + + thread->saved_stack_pointer = stack; + thread->stack_base = stack; + + if (PK_STACK_DIRECTION < 0) { + + thread->stack_limit = stack - stack_size; + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(thread->stack_limit > thread->stack_base, + PK_INVALID_ARGUMENT_THREAD2); + } + + } else { + + thread->stack_limit = stack + stack_size; + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(thread->stack_limit < thread->stack_base, + PK_INVALID_ARGUMENT_THREAD3); + } + } + + thread->semaphore = 0; + thread->priority = priority; + thread->state = PK_THREAD_STATE_SUSPENDED_RUNNABLE; + thread->flags = 0; + + pk_timer_create(&(thread->timer), + __pk_thread_timeout, + (void *)thread); + + __pk_thread_context_initialize(thread, thread_routine, arg); + + return rc; +} + + + + + + + + + + + + + + diff --git a/src/ppe/pk/kernel/pk_thread_util.c b/src/ppe/pk/kernel/pk_thread_util.c new file mode 100644 index 0000000..e69d250 --- /dev/null +++ b/src/ppe/pk/kernel/pk_thread_util.c @@ -0,0 +1,315 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_thread_util.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_thread_util.c +/// \brief PK thread utility APIs +/// +/// The entry points in this file are considered extra routines that will +/// only be included in a PK application that enables threads and uses at +/// least one of these interfaces. + +#include "pk.h" +#include "pk_thread.h" + +/// Get information about a thread. +/// +/// \param thread A pointer to the PkThread to query +/// +/// \param state The value returned through this pointer is the current state +/// of the thread; See \ref pk_thread_states. The caller can set this +/// parameter to the null pointer (0) if this information is not required. +/// +/// \param priority The value returned through this pointer is the current +/// priority of the thread. The caller can set this parameter to the null +/// pointer (0) if this information is not required. +/// +/// \param runnable The value returned through this pointer is 1 if the thread +/// is in state PK_THREAD_STATE_MAPPED and is currently in the run queue +/// (i.e., neither blocked on a semaphore nor sleeping), otherwise 0. The +/// caller can set this parameter to the null pointer (0) if this information +/// is not required. +/// +/// The information returned by this API can only be guaranteed consistent if +/// the API is called from a critical section. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_THREAD_AT_INFO The \a thread is a null (0) pointer. + +int +pk_thread_info_get(PkThread *thread, + PkThreadState *state, + PkThreadPriority *priority, + int *runnable) +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(thread == 0, PK_INVALID_THREAD_AT_INFO); + } + + if (state) { + *state = thread->state; + } + if (priority) { + *priority = thread->priority; + } + if (runnable) { + *runnable = ((thread->state == PK_THREAD_STATE_MAPPED) && + __pk_thread_queue_member(&__pk_run_queue, + thread->priority)); + } + return PK_OK; +} + + +/// Change the priority of a thread. +/// +/// \param thread The thread whose priority will be changed +/// +/// \param new_priority The new priority of the thread +/// +/// \param old_priority The value returned through this pointer is the +/// old priority of the thread prior to the change. The caller can set +/// this parameter to the null pointer (0) if this information is not +/// required. +/// +/// Thread priorities can be changed by the \c pk_thread_priority_change() +/// API. This call will fail if the thread pointer is invalid or if the thread +/// is mapped and the new priority is currently in use. The call will succeed +/// even if the \a thread is suspended, completed or deleted. The +/// application-level scheduling algorithm is completely responsible for the +/// correctness of the application in the event of suspended, completed or +/// deleted threads. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion, including the redundant case of +/// attempting to change the priority of the thread to its current priority. +/// +/// \retval -PK_INVALID_THREAD_AT_CHANGE The \a thread is null (0) or +/// otherwise invalid. +/// +/// \retval -PK_INVALID_ARGUMENT_THREAD_CHANGE The \a new_priority is invalid. +/// +/// \retval -PK_PRIORITY_IN_USE_AT_CHANGE The \a thread is mapped and the \a +/// new_priority is currently in use by another thread. + +int +pk_thread_priority_change(PkThread *thread, + PkThreadPriority new_priority, + PkThreadPriority *old_priority) +{ + PkMachineContext ctx; + PkThreadPriority priority; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(thread == 0, PK_INVALID_THREAD_AT_CHANGE); + PK_ERROR_IF(new_priority > PK_THREADS, + PK_INVALID_ARGUMENT_THREAD_CHANGE); + } + + pk_critical_section_enter(&ctx); + + priority = thread->priority; + + if (priority != new_priority) { + + if (!__pk_thread_is_mapped(thread)) { + + thread->priority = new_priority; + + } else { + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF_CRITICAL(__pk_priority_map[new_priority] != 0, + PK_PRIORITY_IN_USE_AT_CHANGE, + &ctx); + } + + __pk_thread_unmap(thread); + thread->priority = new_priority; + __pk_thread_map(thread); + __pk_schedule(); + } + } + + if (old_priority) { + *old_priority = priority; + } + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + +/// Return a pointer to the thread (if any) mapped at a given priority. +/// +/// \param priority The thread priority of interest +/// +/// \param thread The value returned through this pointer is a pointer to the +/// thread currently mapped at the given priority level. If no thread is +/// mapped, or if the \a priority is the priority of the idle thread, the +/// pointer returned will be null (0). +/// +/// The information returned by this API can only be guaranteed consistent if +/// the API is called from a critical section. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion. +/// +/// \retval -PK_INVALID_ARGUMENT_THREAD_PRIORITY The \a priority is invalid +/// or the \a thread parameter is null (0). + +int +pk_thread_at_priority(PkThreadPriority priority, + PkThread **thread) +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF((priority > PK_THREADS) || (thread == 0), + PK_INVALID_ARGUMENT_THREAD_PRIORITY); + } + + *thread = __pk_thread_at_priority(priority); + + return PK_OK; +} + + +/// Swap thread priorities +/// +/// \param thread_a A pointer to an initialized PkThread +/// +/// \param thread_b A pointer to an initialized PkThread +/// +/// This API swaps the priorities of \a thread_a and \a thread_b. The API is +/// provided to support general and efficient application-directed scheduling +/// algorithms. The requirements on the \a thread_a and \a thread_b arguments +/// are that they are valid pointers to initialized PkThread structures, that +/// the current thread priorities of both threads are legal, and that if a +/// thread is currently mapped, that the new thread priority is not otherwise +/// in use. +/// +/// The API does not require either thread to be mapped, or even to be active. +/// It is legal for one or both of the swap partners to be suspended, deleted +/// or completed threads. The application is completely responsible for the +/// correctness of scheduling algorithms that might operate on inactive or +/// suspended threads. +/// +/// The API does not change the mapped status of a thread. A thread will be +/// mapped after the call of pk_thread_priority_swap() if and only if it was +/// mapped prior to the call. If the new priority of a mapped thread is +/// currently in use (by a thread other than the swap partner), then the +/// PK_PRIORITY_IN_USE_AT_SWAP error is signalled and the swap does not take +/// place. This could only happen if the swap partner is not currently mapped. +/// +/// It is legal for a thread to swap its own priority with another thread. The +/// degenerate case that \a thread_a and \a thread_b are equal is also legal - +/// but has no effect. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion, including the redundant cases that do not +/// actually change priorities, or the cases that assign new priorities to +/// suspended, completed or deleted threads. +/// +/// \retval -PK_INVALID_THREAD_AT_SWAP1 One or both of \a thread_a and +/// \a thread_b is null (0) or otherwise invalid, +/// +/// \retval -PK_INVALID_THREAD_AT_SWAP2 the priorities of One or both of +/// \a thread_a and \a thread_b are invalid. +/// +/// \retval -PK_INVALID_ARGUMENT One or both of the priorities +/// of \a thread_a and \a thread_b is invalid. +/// +/// \retval -PK_PRIORITY_IN_USE_AT_SWAP Returned if a thread is mapped and the +/// new thread priority is currently in use by another thread (other than the +/// swap partner). + +int +pk_thread_priority_swap(PkThread* thread_a, PkThread* thread_b) +{ + PkMachineContext ctx; + PkThreadPriority priority_a, priority_b; + int mapped_a, mapped_b; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF((thread_a == 0) || (thread_b == 0), + PK_INVALID_THREAD_AT_SWAP1); + } + + pk_critical_section_enter(&ctx); + + if (thread_a != thread_b) { + + mapped_a = __pk_thread_is_mapped(thread_a); + mapped_b = __pk_thread_is_mapped(thread_b); + priority_a = thread_a->priority; + priority_b = thread_b->priority; + + if (PK_ERROR_CHECK_API) { + int priority_in_use; + PK_ERROR_IF_CRITICAL((priority_a > PK_THREADS) || + (priority_b > PK_THREADS), + PK_INVALID_THREAD_AT_SWAP2, + &ctx); + priority_in_use = + (mapped_a && !mapped_b && + (__pk_thread_at_priority(priority_b) != 0)) || + (!mapped_a && mapped_b && + (__pk_thread_at_priority(priority_a) != 0)); + PK_ERROR_IF_CRITICAL(priority_in_use, + PK_PRIORITY_IN_USE_AT_SWAP, &ctx); + } + + if (mapped_a) { + __pk_thread_unmap(thread_a); + } + if (mapped_b) { + __pk_thread_unmap(thread_b); + } + thread_a->priority = priority_b; + thread_b->priority = priority_a; + if (mapped_a) { + __pk_thread_map(thread_a); + } + if (mapped_b) { + __pk_thread_map(thread_b); + } + __pk_schedule(); + } + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + diff --git a/src/ppe/pk/kernel/pk_timer_core.c b/src/ppe/pk/kernel/pk_timer_core.c new file mode 100644 index 0000000..334c6e5 --- /dev/null +++ b/src/ppe/pk/kernel/pk_timer_core.c @@ -0,0 +1,425 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_timer_core.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_timer_core.c +/// \brief PK portable kernel timer handler +/// +/// This file contains core routines that would be needed by any application +/// that requires PK timer support at runtime. +/// +/// PK implements a 'tickless' kernel - all events are scheduled at absolute +/// times of the PK timebase. This approach gives the application full +/// control over granularity of event scheduling. Scheduling in absolute time +/// opens up the possibility of scheduling events "in the past". PK +/// uniformly handles this case by scheduling "past" events to occur 1 +/// timebase tick in the future, so that timer callbacks are always run in the +/// expected interrupt context. +/// +/// PK implements the time queue as a simple unordered list of events, plus a +/// dedicated variable that holds the earliest timeout of any event in the +/// list. This is thought to be an appropriate data structure for the +/// following reasons: +/// +/// - PK applications will be small and will not schedule a large number of +/// events. Therefore the cost of scanning the list each time an event times +/// out is balanced against the cost of maintaining the list as a sorted data +/// structure each time an event is added or removed from the event queue. +/// +/// - PK applications may schedule and cancel many, many more events (safety +/// timeouts) than are ever allowed to expire. Events can be added and deleted +/// from the simple DEQUE very quickly since there is no sorting +/// overhead. +/// +/// Events are added to the queue simply by placing them at the end of the +/// queue. If the new event times out earlier than the previous earliest +/// event, the hardware timeout is rescheduled for the new event time. Events +/// are deleted from the queue (cancelled) simply by deleting them. Deletion +/// does not affect the hardware timeout, even if the deleted event would have +/// been the next to time out. It is not an error for the timer handler to +/// take a timer interrupt and find no events pending. Pending events can +/// also be rescheduled in place. +/// +/// When a timeout occurs the event list is scanned from the beginning, and +/// any event that has timed out has its callback processed. +/// Since event and callback processing take +/// time, the list is potentially scanned multiple times until there are no +/// more timed-out events in the list. +/// +/// Note that callbacks are not necessarily processed in time-order. In this +/// sense the PK time queue is like a traditional tick-based time queue in +/// that events are effectively lumped into groups of events that time out +/// together. In a tick-based kernel the 'lump' is the tick interval; here +/// the 'lump' is a variable interval that corresponds to the time it takes to +/// process the entire event list. +/// +/// Timer callbacks are typically run with interrupt preemption enabled. +/// Special callbacks may run without preemption. This is the only part of +/// the PK kernel where data structures of indeterminate size are processed. +/// During processing of the event list by the timer interrupt handler, the +/// consideration of each event always includes a window of preemptability. + +#define __PK_TIMER_CORE_C__ + +#include "pk.h" + +// Declare the timer bottom half handler +static PK_BH_HANDLER(__pk_timer_bh_handler); + +// Define the timer bottom half handler that the interrupt handler will +// schedule +PK_BH_STATIC_CREATE(pk_timer_bh, __pk_timer_bh_handler, 0); + + +// This routine is only used in this file, and will always be called in a +// critical section. + +static inline int +timer_active(PkTimer* timer) +{ + return pk_deque_is_queued((PkDeque*)timer); +} + + +// This is the kernel version of pk_timer_cancel(). +// +// This routine is used here and by thread and semaphore routines. +// External interrupts must be disabled at entry. +// +// If the timer is active, then there is a special case if we are going to +// delete the 'cursor' - that is the timer that __pk_timer_handler() is going +// to handle next. In this case we need to move the cursor to the next timer +// in the queue. +// +// Note that cancelling a timer does not cause a re-evaluation of the next +// timeout. This will happen naturally when the current timeout expires. + +int +__pk_timer_cancel(PkTimer *timer) +{ + int rc; + PkDeque* timer_deque = (PkDeque*)timer; + PkTimeQueue* tq = &__pk_time_queue; + + if (!timer_active(timer)) { + + rc = -PK_TIMER_NOT_ACTIVE; + + } else { + + if (timer_deque == tq->cursor) { + tq->cursor = tq->cursor->next; + } + pk_deque_delete(timer_deque); + rc = 0; + } + return rc; +} + + +// This is the kernel version of pk_timer_schedule(). +// +// This routine is used here and by thread and semaphore routines. +// interrupts must be disabled at entry. +// +// Unless the timer is already active it is enqueued in the doubly-linked +// timer list by inserting the timer at the end of the queue. Then the +// hardware timeout is scheduled if necessary. If the time queue 'cursor' != 0 +// we are in the midst of processing the time queue, and the end of time queue +// processing will schedule the next hardware timemout. + +void +__pk_timer_schedule(PkTimer* timer) +{ + PkTimeQueue* tq = &__pk_time_queue; + + if (!timer_active(timer)) { + pk_deque_push_back((PkDeque*)tq, (PkDeque*)timer); + } + + if (timer->timeout < tq->next_timeout) { + tq->next_timeout = timer->timeout; + if (tq->cursor == 0) { + __pk_schedule_hardware_timeout(tq->next_timeout); + } + } +} + + +// The tickless timer mechanism has timed out. Note that due to timer +// deletions and other factors, there may not actually be a timer in the queue +// that has timed out - but it doesn't matter (other than for efficiency). +// +// This routine must not be entered reentrantly. +// +// First, time out any timers that have expired. Timers in the queue are +// unordered, so we have to check every one. Since passing through the +// loop takes time, we may have to make multiple passes until we know +// that there are no timers in the queue that have already timed +// out. Note that it would also work to only go through the loop once and +// let the hardware scheduler take care of looping, but that would imply +// more overhead than the current implementation. +// +// On each pass through the loop tq->next_timeout computes the minimum timeout +// of events remaining in the queue. This is the only part of the kernel that +// searches a list of indefinite length. Kernel interrupt latency is mitigated +// by running this function as a bottom half. As such, interrupts are only +// disabled when explicitly requested. +// +// Because interrupt preemption is enabled during processing, and preempting +// handlers may invoke time queue operations, we need to establish a pointer +// to the next entry to be examined (tq->cursor) before enabling interupts. +// It's possible that this pointer will be changed by other interrupt handlers +// that cancel the timer pointed to by tq->cursor. +// +// The main loop iterates on the PkDeque form of the time queue, casting each +// element back up to the PkTimer as it is processed. + +static void +__pk_timer_bh_handler(void* arg) +{ + PkMachineContext ctx; + PkTimeQueue* tq; + PkTimebase now; + PkTimer* timer; + PkDeque* timer_deque; + PkTimerCallback callback; + + tq = &__pk_time_queue; + + // Check if we entered the function while it was running in another context. + if (PK_ERROR_CHECK_KERNEL) { + if (tq->cursor != 0) { + PK_PANIC(PK_TIMER_HANDLER_INVARIANT); + } + } + + pk_critical_section_enter(&ctx); + + while ((now = pk_timebase_get()) >= tq->next_timeout) { + tq->next_timeout = PK_TIMEBASE_MAX; + timer_deque = ((PkDeque*)tq)->next; + + // Iterate through the entire timer list, calling the callback of + // timed-out elements and finding the timer that will timeout next, + // which is stored in tq->next_timeout. + while (timer_deque != (PkDeque*)tq) { + + timer = (PkTimer*)timer_deque; + + // Setting this to a non-zero value indicates we are in the middle + // of processing the time queue. + tq->cursor = timer_deque->next; + + if (timer->timeout <= now) { + + // The timer timed out. It is removed from the queue. + // + // The callback may be made with interrupt preemption enabled + // or disabled. However to mitigate kernel interrupt latency + // we go ahead and open up to interrupts after the callback if + // the callback itself was not preemptible. + + pk_deque_delete(timer_deque); + + pk_critical_section_exit(&ctx); + + callback = timer->callback; + if (callback) { + callback(timer->arg); + } + + } else { + + // This timer has not timed out. Its timeout will simply + // participate in the computation of the next timeout. + tq->next_timeout = MIN(timer->timeout, tq->next_timeout); + pk_critical_section_exit(&ctx); + } + + timer_deque = tq->cursor; + pk_critical_section_enter(&ctx); + } + + // Time has passed since we checked the time. Loop back + // to check the time again and see if enough time has passed + // that the next timer has timed out too. + } + + pk_critical_section_exit(&ctx); + + // This marks that we are no longer processing the time queue + tq->cursor = 0; + + // Finally, reschedule the next timeout + __pk_schedule_hardware_timeout(tq->next_timeout); +} + + +void +__pk_timer_handler(void) +{ + //schedule the timer bottom half handler which + //is preemptible. + pk_bh_schedule(&pk_timer_bh); +} + + +/// Schedule a timer for an interval relative to the current time. +/// +/// \param timer The PkTimer to schedule. +/// +/// \param interval The timer will be scheduled to time out at the current +/// time (pk_timebase_get()) plus this \a interval. +/// +/// Once created with pk_timer_create() a timer can be \e scheduled, which +/// queues the timer in the kernel time queue. It is not an error to call \c +/// pk_timer_schedule() on a timer that is already scheduled in the time +/// queue - the timer is simply rescheduled with the new characteristics. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_TIMER_AT_SCHEDULE A a null (0) pointer was provided as +/// the \a timer argument. +/// + +int +pk_timer_schedule(PkTimer *timer, + PkInterval interval) +{ + PkMachineContext ctx; + PkTimebase timeout = pk_timebase_get() + PK_INTERVAL_SCALE(interval); + + pk_critical_section_enter(&ctx); + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(timer == 0, PK_INVALID_TIMER_AT_SCHEDULE); + } + + timer->timeout = timeout; + __pk_timer_schedule(timer); + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + +/// Cancel (dequeue) a timer. +/// +/// \param timer The PkTimer to cancel. +/// +/// Timers can be canceled at any time. It is never an error to call +/// pk_timer_cancel() on an PkTimer object after it is created. Memory used +/// by an PkTimer can be safely reused for another purpose after a successful +/// call ofpk_timer_cancel(). +/// +/// Return values other than PK_OK (0) are not necessarily errors; see \ref +/// pk_errors +/// +/// The following return codes are non-error codes: +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_TIMER_NOT_ACTIVE The \a timer is not currently scheduled, +/// i.e. it was never scheduled or has timed out. This code is returned for +/// information only and is not considered an error. +/// +/// The following return codes are error codes: +/// +/// \retval -PK_INVALID_TIMER_AT_CANCEL The \a timer is a null (0) pointer. +/// + +int +pk_timer_cancel(PkTimer *timer) +{ + PkMachineContext ctx; + int rc = PK_OK; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(timer == 0, PK_INVALID_TIMER_AT_CANCEL); + } + + pk_critical_section_enter(&ctx); + + rc = __pk_timer_cancel(timer); + + pk_critical_section_exit(&ctx); + + return rc; +} + + +/// Get information about a timer. +/// +/// \param timer The PkTimer to query +/// +/// \param timeout The API returns the absolute timeout of the timer through +/// this pointer. If the timer is active, this is the current timeout. If +/// the timer has timed out then this is the previous absolute timeout. If +/// the timer was never scheduled this will be 0. The caller can set this +/// parameter to the null pointer (0) if this information is not required. +/// +/// \param active If the value returned through this pointer is 1 then the +/// timer is active (currently scheduled), otherwise the value will be 0 +/// indicating an inactive timer. The caller can set this parameter to the +/// null pointer (0) if this information is not required. +/// +/// The information returned by this API can only be guaranteed consistent if +/// the API is called from a critical section. +/// +/// Return values other than PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_TIMER_AT_INFO The \a timer is a null (0) pointer. + +int +pk_timer_info_get(PkTimer *timer, + PkTimebase *timeout, + int *active) + +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(timer == 0, PK_INVALID_TIMER_AT_INFO); + } + + if (timeout) { + *timeout = timer->timeout; + } + if (active) { + *active = timer_active(timer); + } + + return PK_OK; +} + +#undef __PK_TIMER_CORE_C__ diff --git a/src/ppe/pk/kernel/pk_timer_init.c b/src/ppe/pk/kernel/pk_timer_init.c new file mode 100644 index 0000000..3ec636d --- /dev/null +++ b/src/ppe/pk/kernel/pk_timer_init.c @@ -0,0 +1,86 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/kernel/pk_timer_init.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_timer_init.c +/// \brief PK timer initialization +/// +/// The entry points in this file might only be used during initialization of +/// the application. In this case the code space for these routines could be +/// recovered and reused after initialization. + +#include "pk.h" + + +/// Create (initialize) a timer. +/// +/// \param timer The PkTimer to initialize. +/// +/// \param callback The timer callback +/// +/// \param arg Private data provided to the callback. +/// +/// Once created with pk_timer_create() a timer can be scheduled with +/// pk_timer_schedule() or pk_timer_schedule_absolute(), which queues the +/// timer in the kernel time queue. Timers can be cancelled by a call of +/// pk_timer_cancel(). +/// +/// Timers created with pk_timer_create() are always run as +/// bottom-half handlers with interrupt preemption enabled. Timer callbacks are +/// free to enter critical sections if required, but must +/// always exit with interrupts enabled. +/// +/// Caution: PK has no way to know if an PkTimer structure provided to +/// pk_timer_create() is safe to use as a timer, and will silently modify +/// whatever memory is provided. +/// +/// Return values other then PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_TIMER_AT_CREATE The \a timer is a null (0) pointer. + +int +pk_timer_create(PkTimer *timer, + PkTimerCallback callback, + void *arg) +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF((timer == 0), PK_INVALID_TIMER_AT_CREATE); + } + + pk_deque_element_create((PkDeque*)timer); + timer->timeout = 0; + timer->callback = callback; + timer->arg = arg; + + return PK_OK; +} + + diff --git a/src/ppe/pk/kernel/pkkernelfiles.mk b/src/ppe/pk/kernel/pkkernelfiles.mk new file mode 100644 index 0000000..599d73b --- /dev/null +++ b/src/ppe/pk/kernel/pkkernelfiles.mk @@ -0,0 +1,56 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/kernel/pkkernelfiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file pkkernelfiles.mk +# +# @brief mk for including architecture independent pk object files +# +# @page ChangeLogs Change Logs +# @section pkkernelfiles.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# Include +########################################################################## + + +########################################################################## +# Object Files +########################################################################## +PK-C-SOURCES = pk_core.c pk_init.c pk_stack_init.c pk_bh_core.c pk_debug_ptrs.c + +PK-TIMER-C-SOURCES += pk_timer_core.c pk_timer_init.c + +PK-THREAD-C-SOURCES += pk_thread_init.c pk_thread_core.c pk_thread_util.c \ + pk_semaphore_init.c pk_semaphore_core.c + +PK_OBJECTS += $(PK-C-SOURCES:.c=.o) + diff --git a/src/ppe/pk/ppe/Makefile b/src/ppe/pk/ppe/Makefile new file mode 100644 index 0000000..51afc5c --- /dev/null +++ b/src/ppe/pk/ppe/Makefile @@ -0,0 +1,74 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/ppe/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# This Makefile compiles all of the PK code required for the PPE port +# of PK. See the "pk.mk" file in this directory. + +#all generated files from this makefile will end up in obj/$(IMAGE_NAME)/pk +export SUB_OBJDIR = /pk + +include img_defs.mk +include pkppefiles.mk + +ifeq "$(PK_TIMER_SUPPORT)" "1" +PPE_OBJECTS += ${PPE-TIMER-C-SOURCES:.c=.o} ${PPE-TIMER-S-SOURCES:.S=.o} +endif + +ifeq "$(PK_THREAD_SUPPORT)" "1" +PPE_OBJECTS += ${PPE-THREAD-C-SOURCES:.c=.o} ${PPE-THREAD-S-SOURCES:.S=.o} +endif + +ifeq "$(PPE_ASYNC_SUPPORT)" "1" +PPE_OBJECTS += ${PPE-ASYNC-C-SOURCES:.c=.o} ${PPE-ASYNC-S-SOURCES:.S=.o} +endif + +OBJS := $(addprefix $(OBJDIR)/, $(PPE_OBJECTS)) + +libpk.a: kernel ppe42 trace ppe + $(AR) crs $(OBJDIR)/libpk.a $(OBJDIR)/*.o + +.PHONY: clean ppe kernel ppe42 trace +ppe: $(OBJS) + +trace: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../trace + +kernel: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../kernel + +ppe42: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../ppe42 + + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +clean: + rm -fr $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/pk/ppe/pk_port.h b/src/ppe/pk/ppe/pk_port.h new file mode 100644 index 0000000..e185170 --- /dev/null +++ b/src/ppe/pk/ppe/pk_port.h @@ -0,0 +1,41 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe/pk_port.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_PORT_H__ +#define __PK_PORT_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_port.h +/// \brief The top-level CME environment header for PK. + +#define HWMACRO_PPE + +#include "ppe42.h" +#include "ppe_timebase.h" + +#endif /* __PK_PORT_H__ */ diff --git a/src/ppe/pk/ppe/pkppefiles.mk b/src/ppe/pk/ppe/pkppefiles.mk new file mode 100644 index 0000000..83b63f7 --- /dev/null +++ b/src/ppe/pk/ppe/pkppefiles.mk @@ -0,0 +1,57 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/ppe/pkppefiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file pkppefiles.mk +# +# @brief mk for including ppe object files +# +# @page ChangeLogs Change Logs +# @section pkppefiles.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# Object Files +########################################################################## + +PPE-C-SOURCES = ppe_init.c +PPE-S-SOURCES = + +PPE-TIMER-C-SOURCES = +PPE-TIMER-S-SOURCES = + +PPE-THREAD-C-SOURCES = +PPE-THREAD-S-SOURCES = + +PPE-ASYNC-C-SOURCES = +PPE-ASYNC-S-SOURCES = + +PPE_OBJECTS += $(PPE-C-SOURCES:.c=.o) $(PPE-S-SOURCES:.S=.o) + diff --git a/src/ppe/pk/ppe/ppe.h b/src/ppe/pk/ppe/ppe.h new file mode 100644 index 0000000..94669d5 --- /dev/null +++ b/src/ppe/pk/ppe/ppe.h @@ -0,0 +1,46 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe/ppe.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PPE_H__ +#define __PPE_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp.h +/// \brief The PPE environment for PK. + +// This is a 'circular' reference in PK, but included here to simplify PGAS +// programming. + +#ifndef HWMACRO_PPE +#define HWMACRO_PPE +#include "ppe42.h" +#endif + +#include "ppe_common.h" + +#endif /* __PPE_H__ */ diff --git a/src/ppe/pk/ppe/ppe_common.h b/src/ppe/pk/ppe/ppe_common.h new file mode 100644 index 0000000..a462e1f --- /dev/null +++ b/src/ppe/pk/ppe/ppe_common.h @@ -0,0 +1,73 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe/ppe_common.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PPE_COMMON_H__ +#define __PPE_COMMON_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe_common.h +/// \brief Common header for PPE +/// +/// This header is maintained as part of the PK port for PPE, but needs to be +/// physically present in the PMX area to allow dropping PMX code as a whole +/// to other teams. + +// -*- WARNING: This file is maintained as part of PK. Do not edit in -*- +// -*- the PMX area as your edits will be lost. -*- + +#ifndef __ASSEMBLER__ +#include <stdint.h> +#endif + +/// This constant is used to define the size of the table of interrupt handler +/// structures as well as a limit for error checking. +/// NOTE: This can be specific to each PPE type (SBE, PPE, GPE) +#define EXTERNAL_IRQS 64 + +#ifdef __ASSEMBLER__ +/// This macro contains PPE specific code. +/// Since standalone models of the PPE do not support external interrupts +/// we just set the code to 64 (phantom interrupt) + .macro hwmacro_get_ext_irq + + li %r4, 64 + + .endm + +/// Redirect the .hwmacro_irq_cfg_bitmaps macro to call our ppe specific implementation +/// This is called from the ppe42_exceptions.S file. +/// NOTE: The standalone version of PPE doesn't support external interrupts so this +/// does nothing. + .macro .hwmacro_irq_cfg_bitmaps + .endm + + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPE_COMMON_H__ */ diff --git a/src/ppe/pk/ppe/ppe_init.c b/src/ppe/pk/ppe/ppe_init.c new file mode 100644 index 0000000..7bbcf6c --- /dev/null +++ b/src/ppe/pk/ppe/ppe_init.c @@ -0,0 +1,49 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe/ppe_init.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe_init.c +/// \brief PK initialization for PPE +/// +/// The entry points in this routine are used during initialization. This +/// code space can be deallocated and reassigned after application +/// initialization if required. + +#include "pk.h" + +/// PPE environment initial setup. +/// +/// This is setup common to all PPE HW Macro applications. This setup takes place +/// during boot, before main() is called. + +void +__hwmacro_setup(void) +{ + //async_initialize(); +} diff --git a/src/ppe/pk/ppe/ppe_timebase.h b/src/ppe/pk/ppe/ppe_timebase.h new file mode 100644 index 0000000..935f4f1 --- /dev/null +++ b/src/ppe/pk/ppe/ppe_timebase.h @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe/ppe_timebase.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PPE_TIMEBASE_H__ +#define __PPE_TIMEBASE_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe_timebase.h +/// \brief support for using the OCB 32 bit timebase register +/// + +#include "pk.h" + +//The timebase register will never be supported in the base ppe model +#ifdef APPCFG_USE_EXT_TIMEBASE +#error "External timebase is not supported on the PPE standalone model" +#endif /* APPCFG_USE_EXT_TIMEBASE */ + +#ifndef __ASSEMBLER__ + +//assembly function is defined in ppe42_timebase.S +uint32_t pk_timebase32_get(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPE_TIMEBASE_H__ */ diff --git a/src/ppe/pk/ppe42/.empty b/src/ppe/pk/ppe42/.empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/pk/ppe42/.empty diff --git a/src/ppe/pk/ppe42/Makefile b/src/ppe/pk/ppe42/Makefile new file mode 100644 index 0000000..8d7ce82 --- /dev/null +++ b/src/ppe/pk/ppe42/Makefile @@ -0,0 +1,50 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/ppe42/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# This Makefile is designed to be invoked with the -I argument set to +# the location of the "pk.mk" for the build + +include img_defs.mk +include pkppe42files.mk + +ifeq "$(PK_TIMER_SUPPORT)" "1" +PPE42_OBJECTS += ${PPE42-TIMER-C-SOURCES:.c=.o} ${PPE42-TIMER-S-SOURCES:.S=.o} +endif + +ifeq "$(PK_THREAD_SUPPORT)" "1" +PPE42_OBJECTS += ${PPE42-THREAD-C-SOURCES:.c=.o} ${PPE42-THREAD-S-SOURCES:.S=.o} +endif + +OBJS := $(addprefix $(OBJDIR)/, $(PPE42_OBJECTS)) + +all: $(OBJS) + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/pk/ppe42/div64.S b/src/ppe/pk/ppe42/div64.S new file mode 100644 index 0000000..ec93250 --- /dev/null +++ b/src/ppe/pk/ppe42/div64.S @@ -0,0 +1,272 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/div64.S $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file div64.S +/// \brief Unsigned 64/64 bit division +/// +/// This is IBM code, originally part of OS Open. The code has been slightly +/// modified from its original form, both to be compatible with PK and to +/// change the function prototype slightly. +/// +/// The code was provided by Matt Tyrlik in Raleigh. + +/* @#START#@ +** +** PSCN (Power Service and Control Network) +** Cage Controller OS Open Code +** +** (C) Copyright International Business Machines Corporation 2002 +** All Rights Reserved +** Licensed Material - Program Property of I B M +** Refer to copyright instructions: Form G120-2083 +** +** Module: +** div64.s +** +** Description: +** Divide 64 bit unsigned values on 32 bit CPU +** div64(uint64_t dividen, uint64_t divisor, +** uint64_t *quotient, uint64_t *remainder) +** +** Original source from: +** "The PowerPC Compiler Writer's Guide", pp62-65 by +** Steve Hoxey, Faraydon Karim, Bill Hay, Hank Warray, +** published by Warthman Associates, 240 Hamilton Avenue, +** Palo Alto, CA 94301, USA, 1996 for IBM. +** ISBN 0-9649654-0-2. +** +** This version checks for divisor equal to zero. +** +** Environment: +** OS Open (XCOFF) +** +** Linkage: +** AIX 4.3.3 +** +** @author +** Thomas Richter +** +** History: +** Date Author Description +** ----------------------------------------------------------------------------- +** 23-Sep-02 Richter Created +** +** @#END#@*/ + + .nolist +#include "pk.h" + .list + + .global_function __ppe42_udiv64 + + /* + ** Code comment notation: + ** msw = most-significant (high-order) word, i.e. bits 0..31 + ** lsw = least-significant (low-order) word, i.e. bits 32..63 + ** LZ = Leading Zeroes + ** SD = Significant Digits + ** + ** R3:R4 = Input parameter, dividend. + ** R5:R6 = Input parameter, divisor. + ** R7 = Output parameter, pointer to quotient. + ** R8 = Output parameter, pointer to remainder. + ** + ** Pointer arguments point to a uint64_t. + ** + ** Division is achieved using a shift/rotate/substract algorithsm + ** described above. + ** The registers are used as follows: + ** R3:R4 = dividend (upper 32bits:lower 32bits) + ** R5:R6 = divisor (upper 32bits:lower 32bits) + ** + ** R7:R8 = temporary 64 bit register (upper 32bits:lower 32bits) + ** count the number of leading 0s in the dividend + ** + ** Here is the description from the book. The dividend is placed + ** in the low order part of a 4 (32bit) register sequence named + ** tmp-high:tmp-low:dividend-high:dividend:low or tmp:dvd for short. + ** + ** Each iteration includes the following steps: + ** 1. Shift tmp:dvd by one bit to the left. + ** 2. Subtract the divisor from tmp. This is a 64 bit operation. + ** 3. If result is greater than or equal, place result in tmp and + ** set the low order bit of dividend + ** 4. If result is negative, do not modify tmp and + ** clear the low order bit of dividend + ** 5. If the number of iterations is less than the width of the + ** dividend, goto step 1. + ** + ** Now the algorithm can be improved by reducing the number of + ** iterations to be executed. + ** 1. Calculate the leading zeroes of the dividend. + ** 2. Calculate the leading zeroes of the divisor. + ** 3. Calculate the significant ones of the dividend. + ** 4. Calculate the significant ones of the divisor. + ** + ** Initial tmp := dvd >> (dvd.SD - dvs.SD) + ** Initial dvd := dvd << (dvd.LZ + dvs.SD) + ** Loops: dvd.SD - dvs.SD. + ** + ** Warning: Special care must be taken if dvd.LZ == dvs.LZ. The code + ** below does so by reducing the number of dvs.SD by one. This leads + ** to the loop being executed 1 more time than really necessary, + ** but avoids to check for the case when dvd.LZ == dvs.LZ. + ** This case (dvd.LZ == dvs.LZ) only checks for the number of leading + ** zeroes, but does not check if dividend is really greater than the + ** divisor. + ** Consider 16/17, both have an LZ value of 59. The code sets dvs.LZ + ** 60. This resutls in dvs.SD to 4, thus one iteration after which + ** tmp is the remainder 16. + */ + +__ppe42_udiv64: // PK + + /* push R30 & R31 onto the stack */ + stwu r1, -16(r1) + stvd r30, 8(r1) + + /* Save result pointers on volatile spare registers */ + ori r31, r8, 0 /* Save remainder address */ + ori r30, r7, 0 /* Save quotient address */ + + /* count the number of leading 0s in the dividend */ + cmpwi cr0, r3, 0 /* dvd.msw == 0? */ + cntlzw r0, r3 /* R0 = dvd.msw.LZ */ + cntlzw r9, r4 /* R9 = dvd.lsw.LZ */ + bne cr0, lab1 /* if(dvd.msw == 0) dvd.LZ = dvd.msw.LZ */ + addi r0, r9, 32 /* dvd.LZ = dvd.lsw.LZ + 32 */ +lab1: + /* count the number of leading 0s in the divisor */ + cmpwi cr0, r5, 0 /* dvd.msw == 0? */ + cntlzw r9, r5 /* R9 = dvs.msw.LZ */ + cntlzw r10, r6 /* R10 = dvs.lsw.LZ */ + bne cr0, lab2 /* if(dvs.msw == 0) dvs.LZ = dvs.msw.LZ */ + cmpwi cr0, r6, 0 /* dvd.lsw == 0? */ + beq cr0, lab10 /* dvs.msw == 0 */ + addi r9, r10, 32 /* dvs.LZ = dvs.lsw.LZ + 32 */ + +lab2: + /* Determine shift amounts to minimize the number of iterations */ + cmpw cr0, r0, r9 /* Compare dvd.LZ to dvs.LZ */ + subfic r10, r0, 64 /* R10 = dvd.SD */ + bgt cr0, lab9 /* if(dvs > dvd) quotient = 0 */ + addi r9, r9, 1 /* See comment above. ++dvs.LZ (or --dvs.SD) */ + subfic r9, r9, 64 /* R9 = dvs.SD */ + add r0, r0, r9 /* (dvd.LZ + dvs.SD) = left shift of dvd for */ + /* initial dvd */ + subf r9, r9, r10 /* (dvd.SD - dvs.SD) = right shift of dvd for */ + /* initial tmp */ + mtctr r9 /* Number of iterations = dvd.SD - dvs.SD */ + + /* R7:R8 = R3:R4 >> R9 */ + cmpwi cr0, r9, 32 /* compare R9 to 32 */ + addi r7, r9, -32 + blt cr0, lab3 /* if(R9 < 32) jump to lab3 */ + srw r8, r3, r7 /* tmp.lsw = dvd.msw >> (R9 - 32) */ + addi r7, r0, 0 /* tmp.msw = 0 */ + b lab4 + +lab3: + srw r8, r4, r9 /* R8 = dvd.lsw >> R9 */ + subfic r7, r9, 32 + slw r7,r3,r7 /* R7 = dvd.msw << 32 - R9 */ + or r8, r8,r7 /* tmp.lsw = R8 | R7 */ + srw r7,r3,r9 /* tmp.msw = dvd.msw >> R9 */ +lab4: + /* R3:R4 = R3:R4 << R0 */ + cmpwi cr0, r0, 32 /* Compare R0 to 32 */ + addic r9, r0, -32 + blt cr0, lab5 /* if(R0 < 32) jump to lab5 */ + slw r3, r4, r9 /* dvd.msw = dvd.lsw << R9 */ + addi r4, r0, 0 /* dvd.lsw = 0 */ + b lab6 + +lab5: + slw r3, r3, r0 /* r3 = dvd.msw << r0 */ + subfic r9, r0, 32 + srw r9, r4, r9 /* r9 = dvd.lsw >> 32 - r0 */ + or r3, r3, r9 /* dvd.msw = r3 | r9 */ + slw r4, r4, r0 /* dvd.lsw = dvd.lsw << r0 */ +lab6: + /* Restoring division shift and subtract loop */ + addi r10, r0, -1 /* r10 = -1 */ + addic r7, r7, 0 /* Clear carry bit before loop starts */ +lab7: + /* + ** tmp:dvd is considered one large register + ** each portion is shifted left 1 bit by adding it to itself + ** adde sums the carry from the previous and creates a new carry + */ + adde r4, r4, r4 /* Shift dvd.lsw left 1 bit */ + adde r3, r3, r3 /* Shift dvd.msw to left 1 bit */ + adde r8, r8, r8 /* Shift tmp.lsw to left 1 bit */ + adde r7, r7, r7 /* Shift tmp.msw to left 1 bit */ + subfc r0, r6, r8 /* tmp.lsw - dvs.lsw */ + subfe. r9, r5, r7 /* tmp.msw - dvs.msw */ + blt cr0, lab8 /* if(result < 0) clear carry bit */ + or r8, r0, r0 /* Move lsw */ + or r7, r9, r9 /* Move msw */ + addic r0, r10, 1 /* Set carry bit */ + +lab8: + bdnz lab7 + + /* Write quotient and remainder */ + adde r4, r4, r4 /* quo.lsw (lsb = CA) */ + adde r3, r3, r3 /* quo.msw (lsb from lsw) */ + stw r4, 4(r30) + stw r3, 0(r30) + stw r8, 4(r31) /* rem.lsw */ + stw r7, 0(r31) /* rem.msw */ + b lab11 + +lab9: + /* Qoutient is 0, divisor > dividend */ + addi r0, r0, 0 + stw r3, 0(r31) /* Store remainder */ + stw r4, 4(r31) + stw r0, 0(r30) /* Set quotient to zero */ + stw r0, 4(r30) + b lab11 + +lab10: + /* Divisor is 0 */ + addi r0, r0, -1 + stw r0, 0(r31) /* Set remainder to zero */ + stw r0, 4(r31) + stw r0, 0(r30) /* Set quotient to zero */ + stw r0, 4(r30) + +lab11: + //pop r30 & r31 from stack + lvd r30, 8(r1) + lwz r1, 0(r1) + blr + .epilogue __ppe42_udiv64 diff --git a/src/ppe/pk/ppe42/pk_port_types.h b/src/ppe/pk/ppe42/pk_port_types.h new file mode 100644 index 0000000..2c80389 --- /dev/null +++ b/src/ppe/pk/ppe42/pk_port_types.h @@ -0,0 +1,65 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/pk_port_types.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_PORT_TYPES_H__ +#define __PK_PORT_TYPES_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_port_types.h +/// \brief Type definitions required by the PK port. +/// +/// \todo GCC provides a portable version of cntlzw called __builtin_clz(). +/// We should make the PK priority queues portable by using this facility. +/// +/// \todo I think that if more of the port-dependent types were moved here, we +/// could break the circular dependencies in some of the header inclusion and +/// simplify the way the PK/port/chip headers are included. + +/// An PkIrqId is an integer in the range of valid interrupts defined by the +/// interrupt controller. + +typedef uint8_t PkIrqId; + +/// PK requires the port to define the type PkThreadQueue, which is a +/// priority queue (where 0 is the highest priority). This queue must be able +/// to handle PK_THREADS + 1 priorities (the last for the idle thread). The +/// port must also define methods for clearing, insertion, deletion and min +/// (with assumed legal priorities). The min operation returns PK_THREADS if +/// the queue is empty. (Or a queue could be initialized with the PK_THREADS +/// entry always present - PK code never tries to delete the idle thread from +/// a thread queue). +/// +/// These queues are used both for the run queue and the pending queue +/// associated with every semaphore. +/// +/// On PPE42 with 32 threads (implied), this is a job for a uint32_t and +/// cntlzw(). + +typedef uint32_t PkThreadQueue; + +#endif /* __PK_PORT_TYPES_H__ */ diff --git a/src/ppe/pk/ppe42/pkppe42files.mk b/src/ppe/pk/ppe42/pkppe42files.mk new file mode 100644 index 0000000..30e19b5 --- /dev/null +++ b/src/ppe/pk/ppe42/pkppe42files.mk @@ -0,0 +1,70 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/ppe42/pkppe42files.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file pkppe42files.mk +# +# @brief mk for including ppe42 object files +# +# @page ChangeLogs Change Logs +# @section pkppe42files.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# Include Files +########################################################################## + + + +########################################################################## +# Object Files +########################################################################## +PPE42-C-SOURCES = ppe42_core.c \ + ppe42_init.c \ + ppe42_irq_core.c\ + ppe42_gcc.c\ + ppe42_scom.c + +PPE42-S-SOURCES = ppe42_boot.S \ + ppe42_exceptions.S\ + div64.S\ + ppe42_timebase.S + +PPE42-TIMER-C-SOURCES = +PPE42-TIMER-S-SOURCES = + +PPE42-THREAD-C-SOURCES += +PPE42-THREAD-S-SOURCES += ppe42_thread_init.S + + +PPE42_OBJECTS += $(PPE42-C-SOURCES:.c=.o) $(PPE42-S-SOURCES:.S=.o) + + + diff --git a/src/ppe/pk/ppe42/ppe42.h b/src/ppe/pk/ppe42/ppe42.h new file mode 100644 index 0000000..0321c49 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42.h @@ -0,0 +1,853 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PPE42_H__ +#define __PPE42_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42.h +/// \brief PPE42 port header for PK + +// Macros to define where declared code is actually compiled + +#ifdef __PPE42_C__ +#define IF__PPE42_CORE_C__(x) x +#define UNLESS__PPE42_CORE_C__(x) +#else +#define IF__PPE42_CORE_C__(x) +#define UNLESS__PPE42_CORE_C__(x) x +#endif + +#ifdef __PPE42_IRQ_CORE_C__ +#define IF__PPE42_IRQ_CORE_C__(x) x +#define UNLESS__PPE42_IRQ_CORE_C__(x) +#else +#define IF__PPE42_IRQ_CORE_C__(x) +#define UNLESS__PPE42_IRQ_CORE_C__(x) x +#endif + +#ifdef HWMACRO_GPE +#include "gpe.h" +#elif defined(HWMACRO_STD) +#include "std.h" +#elif defined(HWMACRO_PPE) +#include "ppe.h" +#else +#error "Macro Type not specified. Are you building from the correct directory?" +#endif + + +#include "ppe42_asm.h" +#include "ppe42_gcc.h" +#include "ppe42_spr.h" +#include "ppe42_msr.h" + + +///start + +/// The synchronization macros defined here all create a compiler +/// memory barrier that will cause GCC to flush/invalidate all memory data +/// held in registers before the macro. This is consistent with other systems, +/// e.g., the PowerPC Linux kernel, and is the safest way to define these +/// macros. + + +// Condition register fields + +#define CR_LT(n) (0x80000000u >> (4 * (n))) +#define CR_GT(n) (0x40000000u >> (4 * (n))) +#define CR_EQ(n) (0x20000000u >> (4 * (n))) +#define CR_SO(n) (0x10000000u >> (4 * (n))) + + +#ifndef __ASSEMBLER__ + +#include "stdint.h" + +/// ssize_t is defined explictly rather than bringing in all of <unistd.h> +#ifndef __ssize_t_defined +#define __ssize_t_defined +typedef int ssize_t; +#endif + +/// A memory barrier +#define barrier() asm volatile ("" : : : "memory") + +/// Ensure In-order Execution of Input/Output +#define eieio() asm volatile ("sync" : : : "memory") + +/// Memory barrier +#define sync() asm volatile ("sync" : : : "memory") + +/// Instruction barrier +#define isync() asm volatile ("sync" : : : "memory") + +/// CouNT Leading Zeros Word +#define cntlzw(x) \ +({uint32_t __x = (x); \ + uint32_t __lzw; \ + asm volatile ("cntlzw %0, %1" : "=r" (__lzw) : "r" (__x)); \ + __lzw;}) + +/// CouNT Leading Zeros : uint32_t +static inline int +cntlz32(uint32_t x) { + return cntlzw(x); +} + +/// CouNT Leading Zeros : uint64_t +static inline int +cntlz64(uint64_t x) { + if (x > 0xffffffff) { + return cntlz32(x >> 32); + } else { + return 32 + cntlz32(x); + } +} + + +/// 32-bit population count +static inline int +popcount32(uint32_t x) +{ + return __builtin_popcount(x); +} + + +/// 64-bit population count +static inline int +popcount64(uint64_t x) +{ + return __builtin_popcountll(x); +} + + +// NB: Normally we wouldn't like to force coercion inside a macro because it +// can mask programming errors, but for the MMIO macros the addresses are +// typically manifest constants or 32-bit unsigned integer expressions so we +// embed the coercion to avoid warnings. + +/// 8-bit MMIO Write +#define out8(addr, data) \ +do {*(volatile uint8_t *)(addr) = (data);} while(0) + +/// 8-bit MMIO Read +#define in8(addr) \ +({uint8_t __data = *(volatile uint8_t *)(addr); __data;}) + +/// 16-bit MMIO Write +#define out16(addr, data) \ +do {*(volatile uint16_t *)(addr) = (data);} while(0) + +/// 16-bit MMIO Read +#define in16(addr) \ +({uint16_t __data = *(volatile uint16_t *)(addr); __data;}) + +/// 32-bit MMIO Write +#define out32(addr, data) \ +do {*(volatile uint32_t *)(addr) = (data);} while(0) + +/// 32-bit MMIO Read +#define in32(addr) \ +({uint32_t __data = *(volatile uint32_t *)(addr); __data;}) + +#ifdef HWMACRO_GPE + +/// 64-bit MMIO Write +#define out64(addr, data) \ + do { \ + uint64_t __data = (data); \ + volatile uint32_t *__addr_hi = (uint32_t *)(addr); \ + volatile uint32_t *__addr_lo = __addr_hi + 1; \ + *__addr_hi = (__data >> 32); \ + *__addr_lo = (__data & 0xffffffff); \ + } while(0) + +#else /* standard PPE's require a 64 bit write */ + +/// 64-bit MMIO Write +#define out64(addr, data) \ +{\ + uint64_t __d = (data); \ + uint32_t* __a = (uint32_t*)(addr); \ + asm volatile \ + (\ + "stvd %1, %0 \n" \ + : "=o"(*__a) \ + : "r"(__d) \ + ); \ +} + +#endif /* HWMACRO_GPE */ + +#ifdef HWMACRO_GPE +/// 64-bit MMIO Read +#define in64(addr) \ + ({ \ + uint64_t __data; \ + volatile uint32_t *__addr_hi = (uint32_t *)(addr); \ + volatile uint32_t *__addr_lo = __addr_hi + 1; \ + __data = *__addr_hi; \ + __data = (__data << 32) | *__addr_lo; \ + __data;}) + +#else /* Standard PPE's require a 64 bit read */ + +#define in64(addr) \ +({\ + uint64_t __d; \ + uint32_t* __a = (uint32_t*)(addr); \ + asm volatile \ + (\ + "lvd %0, %1 \n" \ + :"=r"(__d) \ + :"o"(*__a) \ + ); \ + __d; \ +}) + +#endif /* HWMACRO_GPE */ + +#endif /* __ASSEMBLER__ */ + +#include "ppe42_irq.h" + +#ifndef __ASSEMBLER__ + +/// Store revision information as a (global) string constant +#define REVISION_STRING(symbol, rev) const char* symbol = rev; + +#else // __ASSEMBLER__ + +/// Store revision information as a global string constant + .macro .revision_string, symbol:req, rev:req + .pushsection .rodata + .balign 4 + .global \symbol +\symbol\(): + .asciz "\rev" + .balign 4 + .popsection + .endm + +#endif // __ASSEMBLER__ + + + +#include "ppe42_context.h" + +// PPE42 stack characteristics for PK. The pre-pattern pattern is selected +// to be easily recognizable yet be an illegal instruction. + +#define PK_STACK_DIRECTION -1 +#define PK_STACK_PRE_DECREMENT 1 +#define PK_STACK_ALIGNMENT 8 +#define PK_STACK_TYPE unsigned int +#define PK_STACK_PATTERN 0x03abcdef + +// Kernel data structure offsets for assembler code + +#define PK_THREAD_OFFSET_SAVED_STACK_POINTER 0 +#define PK_THREAD_OFFSET_STACK_LIMIT 4 +#define PK_THREAD_OFFSET_STACK_BASE 8 + +// PK boot loader panic codes + +#define PPE42_BOOT_VECTORS_NOT_ALIGNED 0x00405001 + +// Interrupt handler panic codes + +#define PPE42_DEFAULT_IRQ_HANDLER 0x00405010 +#define PPE42_DEFAULT_SPECIAL_HANDLER 0x00405011 +#define PPE42_PHANTOM_INTERRUPT 0x00405012 +#define PPE42_PROGRAM_HALT 0x00405013 + + +// Exception handling invariant panic codes + +#define PPE42_IRQ_FULL_EXIT_INVARIANT 0x00405020 +#define PPE42_IRQ_FAST2FULL_INVARIANT 0x00405021 + + +// API error panic codes + + +// Application-overrideable definitions + +/// The default thread machine context has MSR[CE], MSR[EE] and MSR[ME] set, +/// and all other MSR bits cleared. +/// +/// The default definition allows external and machine check exceptions. This +/// definition can be overriden by the application. + +#ifndef PK_THREAD_MACHINE_CONTEXT_DEFAULT +#define PK_THREAD_MACHINE_CONTEXT_DEFAULT \ + (MSR_UIE | MSR_EE | MSR_ME) + +#endif + + +#ifndef __ASSEMBLER__ + +/// The PK kernel default panic sequence for C code +/// +/// By default a kernel panic from C code forces external debug mode then +/// generates a \c trap instruction followed by the error code. The \a code +/// argument must be a compile-time integer immediate. This definition can be +/// overriden by the application. +/// +/// The OCC may be running in internal debug mode for various reasons, and +/// TRAP-ing in internal debug mode would lead to an infinite loop in the +/// default Program Interrupt handler - which itself would be a TRAP (since +/// that's the default implementation of PK_PANIC(). Therefore by default +/// the panic is implemented as a special code sequence that forces the core +/// into external debug mode before issuing a TRAP which will halt the core. +/// To preserve the state we use the special global variables +/// __pk_panic_save_dbcr0 and __pk_panic_save_r3 defined in ppe42_core.c. +/// The original value of DBCR0 is destroyed, but can be recovered from the +/// global. In the end %r3 is reloaded from temporary storage and will be +/// unchanged at the halt. +/// +/// Note that there is a small chance that an interrupt will fire and +/// interrupt this code before the halt - in general there is no way around +/// this. +/// +/// The Simics environment does not model Debug events correctly. It executes +/// the TRAP as an illegal instruction and branches to the Program Interrupt +/// handler, destroying the contents of SRR0 and SRR1. Therefore we always +/// insert a special Simics magic breakpoint (which is an effective NOP) +/// before the hardware trap. The special-form magic instruction is +/// recognized by our Simics support scripts which decode the kernel state and +/// try to help the user interpret what happened based on the TRAP code. + +#ifndef PK_PANIC + +/*#define PK_PANIC(code) \ + do { \ + barrier(); \ + asm volatile ("stw %r3, __pk_panic_save_r3@sda21(0)"); \ + asm volatile ("mfdbcr0 %r3"); \ + asm volatile ("stw %r3, __pk_panic_save_dbcr0@sda21(0)"); \ + asm volatile ("lwz %r3, __pk_panic_dbcr0@sda21(0)"); \ + asm volatile ("mtdbcr0 %r3"); \ + asm volatile ("isync"); \ + asm volatile ("lwz %r3, __pk_panic_save_r3@sda21(0)"); \ + asm volatile ("rlwimi 1,1,0,0,0"); \ + asm volatile ("trap"); \ + asm volatile (".long %0" : : "i" (code)); \ + } while (0) +*/ +#define PK_PANIC(code) \ + do { \ + barrier(); \ + asm volatile ("b ."); \ + } while (0) + +// These variables are used by the PK_PANIC() definition above to save and +// restore state. __pk_panic_dbcr0 is the value loaded into DBCR0 to force +// traps to halt the OCC and freeze the timers. + +//#ifdef __PPE42_CORE_C__ +//uint32_t __pk_panic_save_r3; +//uint32_t __pk_panic_save_dbcr0; +//uint32_t __pk_panic_dbcr0 = DBCR0_EDM | DBCR0_TDE | DBCR0_FT; +//#endif + +#endif // PK_PANIC + +/// This is the Simics 'magic breakpoint' instruction. +/// +/// Note that this form does not include a memory barrier, as doing so might +/// change the semantics of the program. There is an alternative form +/// SIMICS_MAGIC_BREAKPOINT_BARRIER that does include a barrier. + +//#define SIMICS_MAGIC_BREAKPOINT asm volatile ("rlwimi 0,0,0,0,0") + +/// This is the Simics 'magic breakpoint' instruction including a memory +/// barrier. +/// +/// Note that the memory barrier guarantees that all variables held in +/// registers are flushed to memory before the breakpoint, however this might +/// change the semantics of the program. There is an alternative form of +/// SIMICS_MAGIC_BREAKPOINT that does not include a barrier. If the idea is +/// to use the breakpoint for tracing code execution in Simics, the barrier +/// form may be preferred so that variable values will be visible in memory. + +/*#define SIMICS_MAGIC_BREAKPOINT_BARRIER \ + asm volatile ("rlwimi 0,0,0,0,0" : : : "memory") +*/ + +#else // __ASSEMBLER__ + +/// This is the Simics 'magic breakpoint' instruction. An assembler macro +/// form is also provided for use within macros. + +//#define SIMICS_MAGIC_BREAKPOINT rlwimi 0,0,0,0,0 + +// .macro _simics_magic_breakpoint +// rlwimi 0,0,0,0,0 +// .endm + +/// The PK kernel panic default panic sequence for assembler code +/// +/// By default a kernel panic from assembler forces external debug mode then +/// generates a \c trap instruction followed by the error code. The \a code +/// argument must be a compile-time integer immediate. This definition can be +/// overriden by the application. +/// +/// See the comments for the non-ASSEMBLER version for further details. Note +/// that the code space reserved for exception handlers is only 8 +/// instructions, so in the assembler context we don't save DBCR0 as doing so +/// would require 10. + +#ifndef PK_PANIC + +#define PK_PANIC(code) _pk_panic code + + .macro _pk_panic, code + b . + .endm + +#endif // PK_PANIC + +#endif // __ASSEMBLER__ + + +// Application-overridible definitions for the PK boot loader + +/// In order to enable the default kernel panic (a trap) to halt the machine, +/// the Debug Control Register 0 (DBCR0) is initialized in externel debug +/// mode, with the Trap Debug Event enabled so that the trap will not cause a +/// program exception, and the FT bit set so that the timers will freeze. +/// This definition can be overridden by the application. +/// +/// NB: It is expected that a reliable production system will redefine all of +/// the 'panic' macros and the default DBCR0 setup. + +#ifndef PPE42_DBCR_INITIAL +#define PPE42_DBCR_INITIAL DBCR_TRAP +#endif + +/// This is the value of the MSR used during initialization. Once PK threads +/// are started (with \c pk_start_threads()), all machine contexts derive +/// from the default thread context \c +/// PK_THREAD_MACHINE_CONTEXT_DEFAULT. This definition can be overriden by +/// the application. +/// +/// The default is to enable machine checks only. + +#ifndef PPE42_MSR_INITIAL +#define PPE42_MSR_INITIAL MSR_ME +#endif + +/// The \a argc argument passed to \c main(). This definition can be overriden +/// by the application. + +#ifndef PPE42_ARGC_INITIAL +#define PPE42_ARGC_INITIAL 0 +#endif + +/// The \a argv argument passed to \c main(). This definition can be overriden +/// by the application. + +#ifndef PPE42_ARGV_INITIAL +#define PPE42_ARGV_INITIAL 0 +#endif + +/// Optionally trap the reset for the debugger, which means that the PPE42 +/// will simply spin at the symbol \c __reset_trap after a chip reset. Set R0 +/// to a non-zero value in the debugger to continue execution. This definition +/// can be overriden by the application. + +#ifndef PPE42_RESET_TRAP +#define PPE42_RESET_TRAP 0 +#endif + +// PPE42 doesn't support the system call instruction so we use this illegal +// instruction to force a program exception which then emulates the system call +// instruction. +#define PPE42_SC_INST 0x44000002 + +#ifndef __ASSEMBLER__ + +/// The PPE42 PK machine context is simply the MSR, a 32-bit integer. + +typedef uint32_t PkMachineContext; + +/// Disable interrupts and return the current +/// context. +/// +/// \param context A pointer to an PkMachineContext, this is the context that +/// existed before interrupts were disabled. Typically this +/// context is restored at the end of a critical section. +/// +/// Return values other then PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_ARGUMENT_INTERRUPT An illegal priority was specified. + +UNLESS__PPE42_CORE_C__(extern) +inline int +pk_interrupt_disable(PkMachineContext *context) +{ + *context = mfmsr(); + + wrteei(0); + + return PK_OK; +} + +/// Set the machine context. +/// +/// \param context A pointer to an PkMachineContext +/// +/// Return values other then PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_ARGUMENT_CONTEXT_SET A null pointer was provided as +/// the \a context argument or an illegal machine context was specified. + +UNLESS__PPE42_CORE_C__(extern) +inline int +pk_machine_context_set(PkMachineContext *context) +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(context == 0, PK_INVALID_ARGUMENT_CONTEXT_SET); + } + + mtmsr(*context); + + return PK_OK; +} + +/// Get the machine context. +/// +/// \param context A pointer to an PkMachineContext. +/// +/// Return values other then PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_ARGUMENT_CONTEXT_GET A null pointer was provided as +/// the \a context argument. + +UNLESS__PPE42_CORE_C__(extern) +inline int +pk_machine_context_get(PkMachineContext *context) +{ + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(context == 0, PK_INVALID_ARGUMENT_CONTEXT_GET); + } + + *context = mfmsr(); + + return PK_OK; +} + +/// The PK kernel thread context switch - PPE42 uses the 'sc' illegal instruction +/// to force a program exception to occur. +#define __pk_switch() asm volatile (".long 0x44000002") + + +/// In the PowerPC EABI all initial stack frames require 8 bytes - the 4 bytes +/// at the SP are zeroed to indicate the end of the stack, and the 4 bytes +/// behind the SP are for the initial subroutine's LR. + +static inline void +__pk_stack_create_initial_frame(PkAddress *stack, size_t *size) \ +{ + *stack -= 8; + *size -= 8; + *((PK_STACK_TYPE *)(*stack)) = 0; +} + +/// The PK Kernel Context for PPE42 +/// +/// The PK portable kernel does not define how the kernel keeps track of +/// whether PK is running, interrupt levels, and other debug +/// information. Instead it defines an API that the port must provide to the +/// portable kernel. +/// +/// In the PPE42 port, the kernel context is maintained in SPRG0. This +/// 32-bit value is treated as 6 distinct fields as indicated in the structure +/// definition. +typedef union { + + uint32_t value; + + struct { + + /// A flag indicating that PK is in thread mode after a call of + /// pk_start_threads(). + unsigned thread_mode : 1; + + /// If this field is non-zero then PK is processing an interrupt + /// and the \c irq field will contain the PkIrqId of the interrupt + /// that kicked off interrupt processing. + unsigned processing_interrupt : 1; + + /// The priority of the currently running thread. In an interrupt + /// context, this is the priority of the thread that was interrupted. + unsigned thread_priority : 6; + + /// This bit tracks whether the current context can be discarded or + /// if the context must be saved. If the processor takes an interrupt + /// and this bit is set, then the current context will be discarded. + /// This bit is set at the end of handling an interrupt and prior + /// to entering the wait enabled state. + unsigned discard_ctx : 1; + + /// The PkIrqId of the currently running (or last run) handler. If + /// \c processing_interrupt is set, then this is the + /// PkIrqId of the IRQ that is currently executing. + unsigned irq : 7; + + /// Each PPE application will define (or not) the interpretation of + /// this field. Since SPRG0 is saved and restored during during thread + /// context switches, this field can be used to record the progress of + /// individual threads. The kernel and/or application will provide + /// APIs or macros to read and write this field. + unsigned app_specific : 16; + + } fields; + +} __PkKernelContext; + +// These APIs are provided for applications to get and set the app_specific +// field of the kernel context which is held in sprg0. + +static inline uint16_t ppe42_app_ctx_get(void) +{ + __PkKernelContext __ctx; + __ctx.value = mfspr(SPRN_SPRG0); + return __ctx.fields.app_specific; +} + +static inline void ppe42_app_ctx_set(uint16_t app_ctx) +{ + PkMachineContext mctx; + __PkKernelContext __ctx; + mctx = mfmsr(); + wrteei(0); + __ctx.value = mfspr(SPRN_SPRG0); + __ctx.fields.app_specific = app_ctx; + mtspr(SPRN_SPRG0, __ctx.value); + mtmsr(mctx); +} + +// These APIs are provided to the PK portable kernel by the port. + +/// PK threads have been started by a call of pk_start_threads(). + +#define __pk_kernel_mode_thread() \ + ({ \ + __PkKernelContext __ctx; \ + __ctx.value = mfspr(SPRN_SPRG0); \ + __ctx.fields.thread_mode;}) + + +/// PK is executing in a thread context (not an interrupt handler). + +#define __pk_kernel_context_thread() \ + ({ \ + __PkKernelContext __ctx; \ + __ctx.value = mfspr(SPRN_SPRG0); \ + __ctx.fields.thread_mode && !__ctx.fields.processing_interrupt;}) + + +/// PK is executing an interrupt handler of any priority. + +#define __pk_kernel_context_any_interrupt() \ + ({ \ + __PkKernelContext __ctx; \ + __ctx.value = mfspr(SPRN_SPRG0); \ + __ctx.fields.processing_interrupt;}) + + +// PK requires the port to define the type PkThreadQueue, which is a +// priority queue (where 0 is the highest priority). This queue must be able +// to handle PK_THREADS + 1 priorities (the last for the idle thread) The +// port must also define methods for clearing, insertion, deletion and min +// (with assumed legal priorities). The min operation returns PK_THREADS if +// the queue is empty (or a queue could be initialized with that entry always +// present - PK code never tries to delete the idle thread from a thread +// queue). +// +// These queues are used both for the run queue and the pending queue +// associated with every semaphore. +// +// On PPE42 with 32 threads (implied), this is a job for a uint32_t and +// cntlzw(). + +static inline void +__pk_thread_queue_clear(volatile PkThreadQueue *queue) +{ + *queue = 0; +} + +static inline void +__pk_thread_queue_insert(volatile PkThreadQueue *queue, PkThreadPriority priority) +{ + *queue |= (0x80000000u >> priority); +} + +static inline void +__pk_thread_queue_delete(volatile PkThreadQueue *queue, PkThreadPriority priority) +{ + *queue &= ~(0x80000000u >> priority); +} + +static inline PkThreadPriority +__pk_thread_queue_min(volatile PkThreadQueue *queue) +{ + return cntlzw(*queue); +} + +static inline int +__pk_thread_queue_member(volatile PkThreadQueue *queue, PkThreadPriority priority) +{ + return ((*queue >> (31 - priority)) & 1); +} + +static inline void +__pk_thread_queue_union(volatile PkThreadQueue *queue0, + volatile PkThreadQueue *queue1) +{ + *queue0 |= *queue1; +} + +static inline int +__pk_thread_queue_count(volatile PkThreadQueue* queue) +{ + return __builtin_popcount(*queue); +} + + +/// This macro is used to call __pk_start_threads() using the kernel stack, +/// in a critical section. + +#define __pk_call_pk_start_threads() \ + do { \ + PkMachineContext ctx; \ + pk_critical_section_enter(&ctx); \ + asm volatile ("mr 1, %0; mtlr %1; blrl" : : \ + "r" (__pk_kernel_stack), \ + "r" (__pk_start_threads)); \ + PK_PANIC(PK_START_THREADS_RETURNED); \ + } while (0) + + +#endif /* __ASSEMBLER__ */ + +/// The __PkKernelContext 'thread_mode' bit as a flag + +#define PPE42_THREAD_MODE 0x8000 +#define PPE42_PROC_IRQ 0x4000 +#define PPE42_DISCARD_CTX 0x0080 + +#define PPE42_THREAD_MODE_BIT 0 +#define PPE42_PROC_IRQ_BIT 1 +#define PPE42_DISCARD_CTX_BIT 8 + +#ifndef __ASSEMBLER__ + +/// Code breakpoints for PPE42 +/// +/// This macro inserts a special PPE42-only breakpoint into the object code +/// at the place the macro invocation appears. This facility is designed for +/// VBU/VPO procedure debugging. This type of breakpoint may not be required +/// on real hardware as we will then have the full power of RISCWatch, gdb, +/// etc. Once inserted into the code, code breakpoints can be enabled or +/// disabled by manipulating the global variable _code_breakpoint_enable, +/// which defaults to 1. +/// +/// The code breakpoint is implemented as a setup routine and a teardown +/// routine, executed in an critical section. The actual break +/// will occur at the address of the call of the teardown routine, in the +/// context of the calling code. The setup routine saves the state of DBCR0/1 +/// and IAC4, then programs the DBCR for an external debug mode, IAC4 +/// breakpoint. The IAC4 breakpoint is set for the address of the call of the +/// teardown routine. The teardown routine simply restores the state of the +/// debug registers that existed before the code breakpoint. +/// +/// Once hit, restarting from the break requires clearing IAC4 and restarting +/// instructions: +/// +/// \code +/// +/// putspr pu.occ iac4 0 +/// cipinstruct pu.occ start +/// +/// \endcode +/// +/// The above restart processes is also encapsulated as the p8_tclEcmd +/// procedure 'unbreakOcc'. +/// +/// In code built for the Simics environment (i.e., with the preprocessor +/// macro SIMICS_ENVIRONMENT=1) this macro simply expands into +/// SIMICS_MAGIC_BREAKPOINT, and simulation can be continued from the break as +/// normal. This Simics magic breakpoint is also under the control of +/// _code_breakpoint_enable. In code not built with SIMICS_ENVIROMENT=1, note +/// that the CODE_BREAKPOINT is ignored by the Simics PPE42 model as it does +/// not model debug events. + +//#if defined(SIMICS_ENVIRONMENT) && (SIMICS_ENVIRONMENT != 0) +/*#define CODE_BREAKPOINT \ + do { \ + if (_code_breakpoint_enable) { \ + SIMICS_MAGIC_BREAKPOINT; \ + } \ + } while (0) +#else +#define CODE_BREAKPOINT \ + do { \ + if (_code_breakpoint_enable) { \ + PkMachineContext __ctx; \ + pk_critical_section_enter(&__ctx); \ + _code_breakpoint_prologue(); \ + _code_breakpoint_epilogue(); \ + pk_critical_section_exit(&__ctx); \ + } \ + } while (0) +#endif +*/ + +//void +//_code_breakpoint_prologue(void); + +//void +//_code_breakpoint_epilogue(void); + +//extern uint32_t _code_breakpoint_enable; + +#endif // __ASSEMBLER__ + + +#endif /* __PPE42_H__ */ diff --git a/src/ppe/pk/ppe42/ppe42_asm.h b/src/ppe/pk/ppe42/ppe42_asm.h new file mode 100644 index 0000000..16b2714 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_asm.h @@ -0,0 +1,632 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_asm.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PPE42_ASM_H__ +#define __PPE42_ASM_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_asm.h +/// \brief Generic assembler macros for 32-bit PPE42 + +// Doxygen is confused by assembler; the best I know how to make it +// work is to put all of the documentation at the beginning like below +// and effectively comment out the code using Doxygen cond/endcond. + +/// \page ppe42_asm Generic assembler macros for 32-bit PPE42 +/// +/// +/// \section _lxzi _l<w,h,b>zi - Load register and Zero from Immediate address +/// +/// These macros encapsulate the 2-instruction sequence required to +/// load from a 32-bit immediate address. +/// +/// \arg \c dreg A register to receive the load data. +/// \arg \c areg A register to hold the immediate address. This can \e +/// not be register 0. Note that if \a areg != \a dreg +/// then \a areg will contain the address at the end of +/// the macro sequence. +/// \arg \c addr A 32-bit immediate address, which may be either an +/// absolute or relocatable expression. +/// +/// Forms: +/// +/// \b _lbzi \a dreg, \a areg, \a addr - Load Byte and Zero from Immediate address \n +/// \b _lhzi \a dreg, \a areg, \a addr - Load Halfword and Zero from Immediate address \n +/// \b _lwzi \a dreg, \a areg, \a addr - Load Word and Zero from Immediate address \n +/// +/// +/// \section _stxi _st<w,h,b>i - STore register to Immediate address +/// +/// These macros encapsulate the 2-instruction sequence required to +/// store to a 32-bit immediate address. +/// +/// \arg \c dreg The register to store. +/// \arg \c areg A register to hold the immediate address. This can \e +/// not be register 0, and can not be the same as \a dreg. +/// Note that \a areg will contain the address at the end of +/// the macro sequence. +/// \arg \c addr A 32-bit immediate address, which may be either an +/// absolute or relocatable expression. +/// +/// Forms: +/// +/// \b _stbi \a dreg, \a areg, \a addr - STore Byte to Immediate address \n +/// \b _sthi \a dreg, \a areg, \a addr - STore Halfword to Immediate address \n +/// \b _stwi \a dreg, \a areg, \a addr - STore Word to Immediate address \n +/// +/// +/// \section _lstzsd _<l,st><w,h,b><z>sd - Load/STore register from/to Small Data area +/// +/// These macros encapulate the small data area relocations for access +/// to storage in the small data sections .sbss, .sdata, .sbss2 and +/// .sdata2. Use of these macros implies small data area support in +/// the compile environment (for variables shared between compiled and +/// assembled code) and initialization code that sets up the small data +/// area registers R13 (and optionally R2). +/// +/// The relocations generated by this macro will work for both SVR4 ABI +/// and EABI environments. In particular, for EABI environments +/// the link editor will insert offsets to either R13 or R2 depending +/// on the section of the symbol. +/// +/// \arg \c dreg The register to load or store. +/// \arg \c addr A 32-bit immediate address, assumed to be a +/// relocatable address in one of the small data sections. +/// +/// Forms: +/// +/// \b _lbzsd \a dreg, \a addr - Load Byte and Zero from Small Data area \n +/// \b _lhzsd \a dreg, \a addr - Load Halfword and Zero from Small Data area \n +/// \b _lwzsd \a dreg, \a addr - Load Word and Zero from Small Data area \n +/// \b _stbsd \a dreg, \a addr - STore Byte to Small Data area \n +/// \b _sthsd \a dreg, \a addr - STore Halfword to Small Data area \n +/// \b _stwsd \a dreg, \a addr - STore Word to Small Data area \n +/// +/// +/// \section _liw _liw<a> - Load Immediate Word (Absolute) +/// +/// These macros encapsulate the two instructions required to load a +/// 32-bit immediate value into a register. If the immediate is an +/// absolute expression, then the \c 'a' form may be able to optimize +/// to a single instruction depending on whether only the high- or +/// low-order bits of the immediate are non-zero. +/// +/// Forms: +/// +/// \b _liw \a rd, \a imm - Load register \a rd with the 32-bit immediate \a imm \n +/// \b _liwa \a rd, \a imm - Load register \a rd with the 32-bit absolute immediate \a imm \n +/// +/// +/// \section _oriwa _oriwa - OR Immediate Word Absolute +/// +/// This macro encapsulates the logical OR of a 32-bit immediate with a +/// register. The immediate value must be an absolute expression. +/// +/// The PowerPC has instructions for OR-ing 16-bit immediates into the +/// upper (\c oris) and lower (\c ori) portions of a register. This +/// macro optimizes the generated code based on which bits (if any) of +/// the absolte immediate are non-zero. +/// +/// This special macro is only provided for the OR function. For other +/// logical operations and recording forms it is necessary in general +/// to first load the 32-bit immediate into a register (e.g., with \c +/// _liwa) then perform the logical operation. +/// +/// \arg \c rd The destination register; at the end will contain \c rs +/// OR \a imm +/// \arg \c rs The source register. +/// \arg \c imm 32-bit absolute expression. +/// +/// Forms: +/// +/// \b _oriwa \a rd, \a rs, \a imm - \a rd gets \a rs OR \a imm \n +/// +/// +/// \section _incr64_fast - 64-bit increment for fast interrupt handlers +/// +/// This macros implements 64-bit counter update in fast interrupt handlers +/// which are forbidden from using the carry-bit in the XER (without +/// saving/restoring it.) +/// +/// \arg \c rs Scratch register +/// \arg \c ra Register containing the counter address at entry +/// +/// \a rs and \a ra must be unique. At the end of the macro the count +/// is updated to memory and \a ra is unmodified. +/// +/// +/// \section _setclear_bits Set/Clear/Copy Bits from Immediate Positions +/// +/// There are situations where it is easier/faster to clear individual bits +/// and bit fields, set bits or copy fields, based on immediate bit numbers +/// and locations, rather than loading masks, since setting up a mask +/// requires 2 instruction in general, whereas these macros generate a single +/// instruction. +/// +/// \arg \c rd - The destination register +/// \arg \c rs - The source register +/// \arg \c n - An immediate size of a bit field, in the range 0 to 32 +/// \arg \c b - An immediate big-endian bit number in the range 0 to 31 +/// +/// Forms: +/// +/// \b _clrfield \a rd, \a rs, \a n, \a b - Clear an \a n bit field from \a rs +/// to \a rd starting from bit \a b \n +/// \b _clrbit \a rd, \a rs, \a b - Clear bit \a b \n +/// \b _setbit \a rd, \a rs, \a b - Set bit \a b \n +/// \b _copyfield \a rd, \a rs, \a n, \a b - Copy an n-bit field from \a rs to +/// \a rd starting from bit \a b \n +/// +/// +/// \section pseudo_ops Assembler Pseudo-Ops Macros +/// +/// Several macros define new 'pseudo-ops'. +/// +/// \subsection cache_align .cache_align +/// +/// The \c .cache_align pseudo-op is used to force alignment on a +/// cache-line boundary. It requires a preprocessor symbol definition for +/// \c LOG_CACHE_LINE_SIZE +/// +/// Forms: +/// +/// \b .cache_align \n +/// +/// +/// \subsection global_function Local and Global Functions +/// +/// The \c .function and \c .global_function pseudo-ops define function +/// symbols in the \c .text section. +/// +/// Forms: +/// +/// \b .function \a symbol - Define a local function \a symbol \n +/// \b .global_function \a symbol - Define a global function \a symbol \n +/// +/// +/// \subsection epilogue .epilogue +/// +/// The \c .epilogue pseudo-op adds size and type information for +/// functions defined in assembler. +/// +/// \arg \c symbol - Assembler epilogue for the function \a symbol. +/// +/// Forms: +/// +/// \b .epilogue \a symbol \n +/// +/// +/// \cond + +#ifdef __ASSEMBLER__ + + +### **************************************************************************** +### _l<b,h,w>zi +### _st<b,h,w>i +### **************************************************************************** + + .macro _lbzi dreg, areg, addr + lis \areg, \addr@ha + .ifc \areg, \dreg + lbz \dreg, \addr@l(\areg) + .else + lbzu \dreg, \addr@l(\areg) + .endif + .endm + + .macro _lhzi dreg, areg, addr + lis \areg, \addr@ha + .ifc \areg, \dreg + lhz \dreg, \addr@l(\areg) + .else + lhzu \dreg, \addr@l(\areg) + .endif + .endm + + .macro _lwzi dreg, areg, addr + lis \areg, \addr@ha + .ifc \areg, \dreg + lwz \dreg, \addr@l(\areg) + .else + lwzu \dreg, \addr@l(\areg) + .endif + .endm + + .macro _stbi dreg, areg, addr + .ifc \areg, \dreg + .err + .endif + lis \areg, \addr@ha + stbu \dreg, \addr@l(\areg) + .endm + + .macro _sthi dreg, areg, addr + .ifc \areg, \dreg + .err + .endif + lis \areg, \addr@ha + sthu \dreg, \addr@l(\areg) + .endm + + .macro _stwi dreg, areg, addr + .ifc \areg, \dreg + .err + .endif + lis \areg, \addr@ha + stwu \dreg, \addr@l(\areg) + .endm + + +### **************************************************************************** +### _l<b,h,w>zsd +### _st<b,h,w>sd +### **************************************************************************** + + .macro _lbzsd dreg, addr + lbz \dreg, \addr@sda21(0) + .endm + + .macro _lhzsd dreg, addr + lhz \dreg, \addr@sda21(0) + .endm + + .macro _lwzsd dreg, addr + lwz \dreg, \addr@sda21(0) + .endm + + .macro _stbsd dreg, addr + stb \dreg, \addr@sda21(0) + .endm + + .macro _sthsd dreg, addr + sth \dreg, \addr@sda21(0) + .endm + + .macro _stwsd dreg, addr + stw \dreg, \addr@sda21(0) + .endm + + +### **************************************************************************** +### _liw<a> +### _oriwa +### **************************************************************************** + + .macro _liw rd, imm + lis \rd, \imm@h + ori \rd, \rd, \imm@l + .endm + + .macro _liwa rd, imm + .if (\imm & 0xffff0000) + lis \rd, \imm@h + .if (\imm & 0xffff) + ori \rd, \rd, \imm@l + .endif + .else + li \rd, \imm@l + .endif + .endm + + .macro _oriwa rd, rs, imm + .if (\imm & 0xffff0000) + oris \rd, \rs, \imm@h + .if (\imm & 0xffff) + ori \rd, \rd, \imm@l + .endif + .else + ori \rd, \rs, \imm@l + .endif + .endm + +### **************************************************************************** +### _incr64_fast +### **************************************************************************** + + .macro _incr64_fast, rs:req, ra:req + + lwz \rs, 4(\ra) + addi \rs, \rs, 1 + cmpwi \rs, 0 + stw \rs, 4(\ra) + bne 233643278f + + lwz \rs, 0(\ra) + addi \rs, \rs, 1 + stw \rs, 0(\ra) +233643278: + + .endm + +### **************************************************************************** +### _clrfield +### _clrbit +### _setbit +### _copyfield +### **************************************************************************** + + .macro _clrfield, rd, rs, n, b + rlwinm \rd, \rs, 0, (\b + \n) & 0x1f, (\b - 1) & 0x1f + .endm + + .macro _clrbit, rd, rs, b + _clrfield \rd, \rs, 1, \b + .endm + + .macro _setbit, rd, rs, b + .ifle \b - 15 + oris \rd, \rs, 1 << (15 - \b) + .else + ori \rd, \rs, 1 << (31 - \b) + .endif + .endm + + .macro _copyfield, rd, rs, n, b + rlwimi \rd, \rs, 0, \b , (\b + \n - 1) + .endm + +### **************************************************************************** +### .cache_align +### .<global_>function +### .epilogue +### **************************************************************************** + + .set _log_cache_line_size, LOG_CACHE_LINE_SIZE + + .macro .cache_align + .align _log_cache_line_size + .endm + + .macro .function symbol + .text + .align 2 + .endm + + .macro .global_function symbol + .text + .align 2 + .global \symbol + .endm + + .macro .epilogue symbol + .type \symbol, @function + .size \symbol, . - \symbol + .endm + +### *************************************************************************** +### 64-bit macros +### *************************************************************************** + +### *************************************************************************** +### Using symbols for register names makes the code more readable and allows +### us to do register arithmetic within macros. +### *************************************************************************** + +.equiv r0, 0 +.equiv r1, 1 +.equiv sp, 1 +.equiv r3, 3 +.equiv r4, 4 +.equiv r5, 5 +.equiv r6, 6 +.equiv r7, 7 +.equiv r8, 8 +.equiv r9, 9 +.equiv r10, 10 + +.equiv r28, 28 +.equiv r29, 29 +.equiv r30, 30 +.equiv r31, 31 + +.equiv d3, 3 +.equiv d4, 4 +.equiv d5, 5 +.equiv d6, 6 +.equiv d7, 7 +.equiv d8, 8 +.equiv d9, 9 +.equiv d10, 10 +.equiv d28, 28 +.equiv d29, 29 +.equiv d30, 30 +.equiv d31, 31 + +### *************************************************************************** +### Load virtual doubleword generic. Load a virtual doubleword from a relocatable +### address expression. If the optional RA is specified, the address remains in +### RA. +### *************************************************************************** +.macro _lvdg DT:req addr:req RA=-1 + .if \RA == -1 + lis \DT, (\addr)@ha + lvd \DT, (\addr)@l(\DT) + .else + lis \RA, (\addr)@ha + lvdu \DT, (\addr)@l(\RA) + .endif +.endm + +### *************************************************************************** +### Load virtual doubleword from a relocatable small data area address +### *************************************************************************** +.macro _lvdsd DT:req addr:req + lvd \DT, (\addr)@sda21(0) +.endm + +### *************************************************************************** +### Store virtual doubleword generic. Store a virtual doubleword based on a +### relocatable address expression. The address remains in RA. +### *************************************************************************** +.macro _stvdg DS:req addr:req RA:req + lis \RA, (\addr)@ha + stvdu \DS, (\addr)@l(\RA) +.endm + +### *************************************************************************** +### Store virtual doubleword to a relocatable small data address expression +### *************************************************************************** +.macro _stvdsd DS:req addr:req + stvd \DS, (\addr)@sda21(0) +.endm + +### *************************************************************************** +### Load virtual doubleword absolute. Set DT to an absolute 64-bit constant +### *************************************************************************** +.macro _lvda DT, cvalue + lwa (\DT + 1)%32, (\cvalue) & 0x00000000ffffffff + lwa \DT, (\cvalue) >> 32 +.endm + +### *************************************************************************** +### +### 64-bit arithmetic macros +### +### *************************************************************************** + +.macro check_overlap2 DA, DB + .if ((\DA - \DB) % 32) == 1 || ((\DA - \DB) % 32) == -1 + .error "virtual doubleword registers must be identical or non-overlapping" + .endif +.endm + +.macro check_overlap3 DA, DB, DC + check_overlap2 \DA, \DB + check_overlap2 \DA, \DC + check_overlap2 \DB, \DC +.endm + +### *************************************************************************** +### Add virtual doubleword carrying +### *************************************************************************** +.macro _addvdc DT, DA, DB + check_overlap3 \DT, \DA, \DB + addc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + adde \DT, \DA, \DB +.endm + +### *************************************************************************** +### Add virtual doubleword to signed 16-bit immediate carrying +### *************************************************************************** +.macro _addvdic DT, DA, SI + .if \DA == 31 + .error "d31 for addend register is not supported" + .endif + check_overlap2 \DT, \DA + addi (\DT+1)%32, \DA+1, SI + addze \DT, \DA +.endm + +### *************************************************************************** +### Add virtual doubleword to unsigned word carrying +### *************************************************************************** +.macro _addvdwuc DT, DA, RB + check_overlap2 \DT, \DA + addc (\DT+1)%32, (\DA+1)%32, \RB + addze \DT, \DA +.endm + +### *************************************************************************** +### Subtract virtual doubleword carrying +### *************************************************************************** +.macro _subvdc DT, DA, DB + check_overlap3 \DT, \DA, \DB + subfc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + subfe \DT, \DA, \DB +.endm + +### *************************************************************************** +### +### 64-bit logic macros +### +### *************************************************************************** + +### *************************************************************************** +### AND virtual doubleword +### *************************************************************************** +.macro _andvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + and (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + and \DT, \DA, \DB +.endm + +### *************************************************************************** +### ANDC virtual doubleword +### *************************************************************************** +.macro _andcvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + andc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + andc \DT, \DA, \DB +.endm + +### *************************************************************************** +### EQV virtual doubleword +### *************************************************************************** +.macro _eqvvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + eqv (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + eqv \DT, \DA, \DB +.endm + +### *************************************************************************** +### OR virtual doubleword +### *************************************************************************** +.macro _orvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + or (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + or \DT, \DA, \DB +.endm + +### *************************************************************************** +### ORC virtual doubleword +### *************************************************************************** +.macro _orcvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + orc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + orc \DT, \DA, \DB +.endm + +### *************************************************************************** +### XOR virtual doubleword +### *************************************************************************** +.macro _xorvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + xor (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + xor \DT, \DA, \DB +.endm + +#endif /* __ASSEMBLER__ */ + +/// \endcond + +// Local Variables: +// mode:asm +// End: + +#endif /* __PPE42_ASM_H__ */ diff --git a/src/ppe/pk/ppe42/ppe42_boot.S b/src/ppe/pk/ppe42/ppe42_boot.S new file mode 100644 index 0000000..f237690 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_boot.S @@ -0,0 +1,193 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_boot.S $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_boot.S +/// \brief PK bootloader for PPE42 + + .nolist +#include "pk.h" + .list + +### PK Bootloader for PPE42 +### +### This is the basic restart initialization of the processor. +### Parts of this code were derived from examples in the IBM OSopen +### OpenBIOS for the 405GP written by James Burke. +### +### This code does not really do very much, just makes sure that there will +### be a reasonable state in the machine when control is turned over to +### the PK application. Any core setup that requires SPR access will be done +### here. All other setup is expected to take place in system-specific +### routines. +### +### From the PowerPC 405-S Embedded Core User's manual: +### +### "In general, the contents of SPRs are undefined after a core, chip or +### system reset. Some SPRs retain the content they had before the reset +### occurred." +### +### Registers fully reset: +### DBCR1 - Data compares disabled +### DCWR - Data cache write-through disabled +### ESR - No exception syndromes +### MSR - No exceptions/interrupts are allowed +### +### Registers partially reset: +### CCR0 = 0x00700000 - Sets ICU and DCU PLB Priority +### DBCR0 [EDM] = 0 - External debug mode disabled +### [RST] = 0 - No reset action +### DBSR [MRR] = x - x indicates most recent reset action +### SGR = 0xffffffff - Storage is guarded +### TCR [WRC] = 0 - Watchdog timer reset disabled +### TSR [WRS] = x - x is a copy of TCR[WRC] Watchdog reset status +### [PIS] = x - undefined + + .global_function __pk_boot + .global __reset_trap + +__pk_boot: + + ## Trap the reset for the debugger. Set R0 to a non-zero value in the + ## debugger to continue. + + .if PPE42_RESET_TRAP + li %r0, 0 +__reset_trap: + cmpwi %r0, 0 + beq __reset_trap + .endif + + ## Set up PowerPC EABI constant registers. These registers are never + ## again touched by the PK kernel or the application (if they are + ## behaving). + + _liw %r2, _SDA2_BASE_ + _liw %r13, _SDA_BASE_ + + ## Clear the timer control register. This masks all timer interrupts. + + li %r3, 0 + mttcr %r3 + + ## The stack pointer is initialized for use by the remainder of the + ## initialization, including the application main(). The linker script + ## defines the initial stack area. + ## + ## Stacks are always 8-byte aligned. A '0' is stored at the + ## stack pointer to indicate the end of the stack chain. Stack frames + ## always consist of at least 8 bytes - the backchain pointer and the + ## slot above the backchain pointer for the callee's LR. + + _liw %r1, _PK_INITIAL_STACK + _clrfield %r1, %r1, 3, 29 # 8-byte align + li %r3, 0 + stwu %r3, -8(%r1) + + ## SPRG0 (__PkKernelContext) is initialized to 0 + ## indicating that the PK kernel is not in thread mode, and no + ## interrupts are active. + + li %r3, 0 + mtsprg0 %r3 + + ## Set up the initial value of Debug Control Register 0. Note that + ## DBCR1 is specified to be cleared at reset. VBU simulation requested + ## an option that this register not be modified so that they could + ## completely control debug behavior from reset of the PPE42. + +#ifndef NO_INIT_DBCR0 + _liwa %r3, PPE42_DBCR_INITIAL + mtdbcr %r3 +#endif + + ## The exception vector prefix is set - it must be 512 byte aligned. + ## NOTE: for PPE42, the IVPR is read only, but can be changed through scoms + + #_liw %r3, __vectors + #andi. %r4, %r3, 0x01ff + #beq 1f + #_pk_panic PPE42_BOOT_VECTORS_NOT_ALIGNED +#1: + #mtivpr %r3 + #sync + + ## The MSR to be used during the rest of intialization is + ## established. This MSR should NOT enable + ## interrupts, but could enable machine check exceptions. + + _liwa %r3, PPE42_MSR_INITIAL + mtmsr %r3 + sync + +#ifdef PK_BOOT_FROM_ROM + + ## NB: I don't think the old linker scripts were necessarily the most + ## optimal. We need to revisit this if we actually do ROM boots in PK + ## Version 2. Not sure the comments are correct. + + ## Data is copied from the initial ROM image to the RAM. The + ## address symbols are defined in the linker command file. The linker + ## will have zeroed this area in the ROM image. + + liw %r3, __pk_ram_lma - 4 # src + liw %r4, __pk_ram_vma - 4 # dest + liw %r5, __pk_ram_size + liw %r6, 2 + srw %r5, %r5, %r6 # Number of word transfers + mtctr %r5 + +copy_loop: + lwzu %r5, 4(%r3) + stwu %r5, 4(%r4) + bdnz copy_loop + +#endif /* PK_BOOT_FROM_ROM */ + + + ## Call the system setup code. + + bl __ppe42_system_setup + + ## Call the application. If for some reason we return from + ## the call of the application we call an alternate entry point of the + ## idle thread. + ## + ## An initial argc/argv can be passed into main(). argc is expected to + ## be a 32-bit immediate integer, and argv is expected to be a 32-bit + ## absolute or relocatable expression. + + _liwa %r3, PPE42_ARGC_INITIAL + _liw %r4, PPE42_ARGV_INITIAL + bl __pk_main + + b __pk_idle_thread_from_bootloader + + .epilogue __pk_boot + diff --git a/src/ppe/pk/ppe42/ppe42_cache.h b/src/ppe/pk/ppe42/ppe42_cache.h new file mode 100644 index 0000000..16340f0 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_cache.h @@ -0,0 +1,126 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_cache.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PPE42_CACHE_H__ +#define __PPE42_CACHE_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_cache.h +/// \brief PowerPC-lite (PPE) cache management header for PK +/// +/// The data cache flush/invalidate macros defined here create a compiler +/// memory barrier that will cause GCC to flush/invalidate all memory data +/// held in registers before the macro. + +#ifndef __ASSEMBLER__ + +/// Determine cache-alignment of a pointer or byte-count +#define cache_aligned(x) \ + ((((unsigned long)(x)) & (POW2_32(LOG_CACHE_LINE_SIZE) - 1)) == 0) + +/// Cache-align a pointer or byte count. If the 'direction' is <= 0 then we +/// round down, else round up. +#define cache_align(x, direction) \ + ({ \ + unsigned long __x = (unsigned long)(x); \ + unsigned long __r; \ + if ((direction) <= 0) { \ + __r = __x & ~(((unsigned long)CACHE_LINE_SIZE) - 1); \ + } else { \ + if (__x % CACHE_LINE_SIZE) { \ + __r = __x + (CACHE_LINE_SIZE - (__x % CACHE_LINE_SIZE)); \ + } \ + } \ + (void *)__r; \ + }) + +/// Data Cache Block Flush +#define dcbf(p) asm volatile ("dcbf 0, %0" : : "r" (p) : "memory") + +/// Data Cache Block Touch +#define dcbt(p) asm volatile ("dcbt 0, %0" : : "r" (p) : "memory") + +/// Data Cache Block Invalidate (Privileged) +#define dcbi(p) asm volatile ("dcbi 0, %0" : : "r" (p) : "memory") + +void +dcache_invalidate_all(void); + +void +dcache_flush_all(void); + +void +dcache_invalidate(void *p, size_t bytes); + +void +dcache_flush(void *p, size_t bytes); + +/// Invalidate a line in the D-cache +/// +/// \param p An address withing the cache line to be invalidated. +/// +/// The dcache_invalidate_line() API is used to invalidate a single cache line +/// containing the address \a p. Note that invalidation is a destructive +/// operation that may cause the loss of information. It is the caller's +/// responsibility to insure that no useful data is inadverdently invalidated. +/// D-cache invalidation is more-or-less a no-op for data either not in the +/// cache or marked as non-cacheable. +/// +/// This API always issues a sync() after the invalidation. + +static inline void +dcache_invalidate_line(void *p) +{ + dcbi(p); + sync(); +} + +/// Flush and invalidate a line from the D-cache +/// +/// \param p An address within the cache line to be flushed. +/// +/// The dcache_flush_line() API can be used as a shortcut to flush and +/// invalidate a single cache line. Note that flushing is not a destructive +/// operation in the sense that no information is lost, however the caller +/// must make sure that the entirity of the data to be flushed is contained in +/// the line that includes the address \a p. D-cache flush is more-or-less a +/// no-op for data either not in the cache or marked as non-cacheable. +/// +/// This API always issues a sync() after the flush. + +static inline void +dcache_flush_line(void *p) +{ + dcbf(p); + sync(); +} + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPE42_CAHE_H__ */ diff --git a/src/ppe/pk/ppe42/ppe42_context.h b/src/ppe/pk/ppe42/ppe42_context.h new file mode 100644 index 0000000..68d29e3 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_context.h @@ -0,0 +1,225 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_context.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PPE42_CONTEXT_H__ +#define __PPE42_CONTEXT_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_context.h +/// \brief PPE42 Machine and Thread context for PK + +/// \page ppe42_machine_context PPE42 Assembler Macros for PK Machine +/// Context (Critical Sections) +/// +/// \section _pk_enter_critical \b _pk_critical_section_enter/exit +/// +/// These macro encapsulates the instruction sequences required to enter and +/// exit critical sections, along with the machine context save for later +/// exiting the critical section. +/// +/// \arg \c ctxreg A register that will hold (holds) the machine context (MSR) +/// prior to entering the critical section (to be restored) for \c +/// _pk_critical_section_enter (\c _pk_critical_section_exit). +/// +/// \arg \c scrreg A scratch register required for the computation of +/// \c _pk_critical_section_enter. +/// +/// Forms: +/// +/// \b _pk_critical_section_enter \a priority, \a ctxreg, \a scrreg - Enter a +/// critical section \n +/// \b _pk_critical_section_exit \a ctxreg - Exit a critical section + +#ifdef __ASSEMBLER__ + + .set _msr_ee_bit, MSR_EE_BIT + + .macro _pk_critical_section_enter ctxreg, scrreg + mfmsr \ctxreg + wrteei 0 + .endm + + .macro _pk_critical_section_exit ctxreg + mtmsr \ctxreg + .endm + +// **************************************************************************** +// PK context save/restore macros for 32-bit Embedded PowerPC +// **************************************************************************** + +// All stack frames are 8-byte aligned in conformance with the EABI. PK +// never saves or restores GPR2 or GPR13. GPR13 is constant in (E)ABI +// applications - the base of the read-write small data area. GPR2 is +// system-reserved in ABI applications, and is the base for read-only small data +// in EABI applications. + +// USPRG0 holds the __PkKernelContext structure (defined in ppe42.h) that +// represents the current kernel context. The layout is as follows: +// +// Bits Meaning +// ============== +// 0 The 'thread_mode' flag +// 1 The 'processing_interrupt" flag +// 2:7 The thread priority of the running thread +// 8 The 'discard_ctx' flag +// 9:15 The IRQ currently being processed +// 16:31 The application specific data +// +// When PK is initialized USPRG0 is initialized to 0. When thread-mode is +// entered (by pk_start_threads()) bit 0 is set to 1. If desired, +// once initialized (with pk_initialize()) PK can simply +// handle interrupts, reverting back to the non-thread-mode idle loop when +// there's nothing to do. +// + + ## ------------------------------------------------------------ + ## Unused registers for embedded PPE42` + ## ------------------------------------------------------------ + + ## Registers GPR2 and GPR13 are never saved or restored. In ABI and + ## EABI applications these registers are constant. + + .set UNUSED_GPR2, 0x2 # Dedicated; EABI read-only small data area + .set UNUSED_GPR13, 0xd # Dedicated; (E)ABI read-write small data area + + ## ------------------------------------------------------------ + ## The PK context layout for Embedded PPE42 + ## ------------------------------------------------------------ + + .set PK_CTX_GPR1, 0x00 # Dedicated; Stack pointer + .set PK_CTX_LINKAGE, 0x04 # Slot for handler to store LR + .set PK_CTX_GPR3, 0x08 # Volatile; Parameter; Return Value + .set PK_CTX_GPR4, 0x0c # Volatile; Parameter + .set PK_CTX_GPR5, 0x10 # Volatile; Parameter + .set PK_CTX_GPR6, 0x14 # Volatile; Parameter + .set PK_CTX_CR, 0x18 # Condition register + .set PK_CTX_LR, 0x1c # Link register + + .set PK_CTX_GPR7, 0x20 # Volatile; Parameter + .set PK_CTX_GPR8, 0x24 # Volatile; Parameter + .set PK_CTX_GPR9, 0x28 # Volatile; Parameter + .set PK_CTX_GPR10, 0x2c # Volatile; Parameter + .set PK_CTX_GPR28, 0x30 # Non-volatile + .set PK_CTX_GPR29, 0x34 # Non-volatile + .set PK_CTX_GPR30, 0x38 # Non-volatile + .set PK_CTX_GPR31, 0x3c # Non-volatile + + .set PK_CTX_XER, 0x40 # Fixed-point exception register + .set PK_CTX_CTR, 0x44 # Count register + .set PK_CTX_SRR0, 0x48 # Save/restore register 0 + .set PK_CTX_SRR1, 0x4c # Save/restore register 1 + .set PK_CTX_GPR0, 0x50 # Volatile; Language specific + .set PK_CTX_KERNEL_CTX, 0x54 # Saved __PkKernelContext for IRQ + + .set PK_CTX_SIZE, 0x58 # Must be 8-byte aligned + + ## ------------------------------------------------------------ + ## Push the interrupted context if necessary + ## + ## This macro saves off some context in preparation for calling + ## the pk_ctx_check_discard routine. This is an attempt to use + ## the 32 byte cache more efficiently. + ## + ## 8 Instructions + ## ------------------------------------------------------------ + ## + + .macro _pk_ctx_push_as_needed branch_addr:req + + stwu %r1, -PK_CTX_SIZE(%r1) + stvd %d3, PK_CTX_GPR3(%r1) + mfcr %r3 + mflr %r4 + stvd %d3, PK_CTX_CR(%r1) + _liw %r3, \branch_addr + b ctx_check_discard + .endm + + + ## ------------------------------------------------------------ + ## update the kernel context in response to an interrupt. + ## ------------------------------------------------------------ + + ## The kernel context is updated with the currently active + ## IRQ in bits 9:15. + + .macro _update_kernel_context irqreg, ctxreg + rlwimi \ctxreg, \irqreg, 16, 9, 15 //set the irq # + oris \ctxreg, \ctxreg, 0x4000 //set the 'processing_interrupt' flag + mtsprg0 \ctxreg + +#if PK_KERNEL_TRACE_ENABLE + mr %r31, \irqreg + srwi \ctxreg, \ctxreg, 16 + PK_KERN_TRACE_ASM16("INTERRUPT_CONTEXT(0x%04x)", \ctxreg) + mr \irqreg, %r31 +#endif + + .endm + +#else /* __ASSEMBLER__ */ + +/// PK thread context layout as a C structure. +/// +/// This is the structure of the stack area pointed to by +/// thread->saved_stack_pointer when a thread is fully context-switched out. + +typedef struct { + uint32_t r1; + uint32_t linkage; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t cr; + uint32_t lr; + + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r28; + uint32_t r29; + uint32_t r30; + uint32_t r31; + + uint32_t xer; + uint32_t ctr; + uint32_t srr0; + uint32_t srr1; + uint32_t r0; + uint32_t sprg0; + +} PkThreadContext; + + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPE42_CONTEXT_H__ */ + + diff --git a/src/ppe/pk/ppe42/ppe42_core.c b/src/ppe/pk/ppe42/ppe42_core.c new file mode 100644 index 0000000..ad4b2c3 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_core.c @@ -0,0 +1,150 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_core.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_core.c +/// \brief The final bits of PK runtime code required to complete the PPE42 +/// port. +/// +/// The entry points in this file are considered 'core' routines that will +/// always be present during runtime in any PK application. + +#define __PPE42_CORE_C__ + +#include "pk.h" + +typedef union +{ + uint64_t value; + struct + { + uint32_t dec_start; + uint32_t dec_change_tag; + }; +}ppe42_timebase_data_t; + +ppe42_timebase_data_t ppe42_tb_data = {0}; +PkTimebase ppe42_64bit_timebase = 0; + + +#if PK_TIMER_SUPPORT + +// The tickless kernel timer mechanism for PPE42 +// +// This routine must be called from a critical section. +// +// Tickless timeouts are provided by programming the PIT timer based on when +// the next timeout will occur. If the timeout is for the end of time there's +// nothing to do - PK does not use auto-reload mode so no more PIT interrupts +// will be arriving. Otherwise, if the timeout is longer than the 32-bit PIT +// timer can handle, we simply schedule the timeout for 2**32 - 1 and +// __pk_timer_handler() will keep rescheduling it until it finally occurs. +// If the \a timeout is in the past, we schedule the PIT interrupt for 1 tick +// in the future in accordance with the PK specification. + +#ifndef APPCFG_USE_EXT_TIMEBASE +void +__pk_schedule_hardware_timeout(PkTimebase timeout) +{ + PkTimebase now; + uint32_t new_dec; + uint32_t dec; + + if (timeout != PK_TIMEBASE_MAX) { + + now = pk_timebase_get(); + + if (timeout <= now) { + new_dec = 1; + } else if ((timeout - now) > 0xffff0000) { + new_dec = 0xffff0000; + } else { + new_dec = timeout - now; + } + + //read and write the DEC back-to-back so that we lose as little time + //as possible + dec = mfspr(SPRN_DEC); + mtspr(SPRN_DEC, new_dec); + + //update our 64bit accumulator with how much time has advanced since + //we last changed it. + ppe42_64bit_timebase += ppe42_tb_data.dec_start - dec; + + //update our start time so we know how much time has advanced since + //this update of the accumulator + ppe42_tb_data.dec_start = new_dec; + ppe42_tb_data.dec_change_tag++; + } +} + +#else + +void +__pk_schedule_hardware_timeout(PkTimebase timeout) +{ + PkTimebase now; + PkTimebase diff; + uint32_t new_dec; + + if (timeout != PK_TIMEBASE_MAX) { + + now = pk_timebase_get(); + + //update our 64bit accumulator with the current snapshot + ppe42_64bit_timebase = now; + + if (timeout <= now) + { + new_dec = 1; + } + else + { + diff = (timeout - now); + + if (diff > 0xfffffffful) + { + new_dec = 0xffffffff; + } + else + { + new_dec = diff; + } + } + + mtspr(SPRN_DEC, new_dec); + + } +} + +#endif /* APPCFG_USE_EXT_TIMEBASE */ + +#endif /* PK_TIMER_SUPPORT */ + +#undef __PPE42_CORE_C__ diff --git a/src/ppe/pk/ppe42/ppe42_exceptions.S b/src/ppe/pk/ppe42/ppe42_exceptions.S new file mode 100644 index 0000000..9d79429 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_exceptions.S @@ -0,0 +1,521 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_exceptions.S $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_exceptions.S +/// \brief PPE42 exception vector area. +/// +/// \cond + + .nolist +#include "pk.h" + .list + +## declare and initializes global variables that hold external irq config data +## Each PPE macro type (GPE, CME, and SBE) will have it's own implementation of this macro +## defined in (gpe, cme, sbe)_common.h + .hwmacro_irq_cfg_bitmaps + +### **************************************************************************** +### .vectors - This section contains all ppe42 exception vectors +### +### **************************************************************************** + + .section .vectors, "ax", @progbits + + .global __vectors + +__vectors: + + ############################################################ + # 0x0000 : Machine Check + ############################################################ + + ### Unmaskable interrupts (including program interrupts) are promoted + ### to machine check interrupts if MSR[UIE] = 0 and MSR[ME] = 1. + ### If the machine check was caused by a program interrupt it + ### will be forwarded to the program exception handler. +__machine_check: + + PPE42_MACHINE_CHECK_HANDLER + + ############################################################ + # 0x0040 : System Reset + ############################################################ + .global __system_reset + .org __vectors + 0x0040 +__system_reset: + b __pk_boot + + ############################################################ + # 0x0060 : Data Storage Interrupt + ############################################################ + + .org __vectors + 0x0060 +__data_storage: + + PPE42_DATA_STORAGE_HANDLER + + ############################################################ + # 0x0080 : Instruction Storage Interrupt + ############################################################ + + .org __vectors + 0x0080 +__instruction_storage: + + PPE42_INSTRUCTION_STORAGE_HANDLER + + + ############################################################ + # 0x00A0 : External Interrupt + ############################################################ + + .org __vectors + 0x00A0 +__external_interrupt_vector: + _pk_ctx_push_as_needed __get_ext_irq + + ############################################################ + # 0x00C0 : Alignment Exception + ############################################################ + + .org __vectors + 0x00C0 +__alignment_exception: + + PPE42_ALIGNMENT_HANDLER + + + ############################################################ + # 0x00E0 : Program Interrupt + ############################################################ + + .org __vectors + 0x00E0 + + ### Program exceptions are utilized for emulating the system call + ### instruction (0x44000002) which is used for doing context + ### switches between threads. They can also be used by the code + ### to signal an exception in an error scenario. +__program_exception: + _pk_ctx_push_as_needed program_exception_handler + + + ############################################################ + # 0x0100 : DEC Interrupts + ############################################################ + + .org __vectors + 0x0100 +__dec_interrupt: + _pk_ctx_push_as_needed dec_handler + + ############################################################ + # 0x0120 : FIT Interrupts + ############################################################ + .org __vectors + 0x0120 +__fit_interrupt: + + _pk_ctx_push_as_needed fit_handler + + ############################################################ + # 0x0140 : Watchdog Interrupts + ############################################################ + .org __vectors + 0x0140 +__watchdog_interrupt: + + _pk_ctx_push_as_needed watchdog_handler + + +### **************************************************************************** +### The rest of the code in this file doesn't have to be placed anywhere +### special, so just place it in the .text section. +### **************************************************************************** + + .section .text, "ax", @progbits + + + ## The idle thread has no permanent register context. The idle thread + ## entry point is re-entered whenever the idle thread is scheduled. + + .global __pk_idle_thread + .global __pk_idle_thread_from_bootloader + +__pk_idle_thread: + + ## The idle thread 'uses' the kernel stack. Any register context + ## pushed here is redundant and is wiped out/ignored every time the + ## idle thread is re-scheduled. + + ## The idle thread simply establishes a default machine context and + ## enters the wait-enable state. The idle thread is always entered + ## with interrupts disabled. + ## + ## The kernel context is initialized to indicate that the idle thread + ## is running - the idle thread priority is PK_THREADS, the + ## 'thread-mode' bit is asserted and so is the 'discard-ctx" bit. + ## In addition, the previous kernel context is stored in the lower + ## 16 bits. + ## + ## This loop can also be called from the PK bootloader if main() + ## returns - in which case we don't muck with the SPRG0 or the stack + ## pointer. + mfsprg0 %r3 + srwi %r3, %r3, 16 + oris %r3, %r3, (PK_THREADS << 8) | PPE42_THREAD_MODE | PPE42_DISCARD_CTX + mtsprg0 %r3 + _lwzsd %r1, __pk_kernel_stack + +__pk_idle_thread_from_bootloader: + + PK_KERN_TRACE_ASM16("ENTER_IDLE_STATE") + + _lwzsd %r3, __pk_thread_machine_context_default + _oriwa %r3, %r3, MSR_WE + mtmsr %r3 + b . + + ## pk_halt() is implemented on the ppe42 by writing a value of 0x3 to + ## the RST field of the DBCR. + .global pk_halt +pk_halt: + lis %r31, 0x3000 + mtdbcr %r31 + .long 0 + + +dec_handler: + + ## The portable timer handler of PK is a full-mode handler with the prototype: + ## void (*pk_timer_handler)(void). + ## + ## To support the portable specification, the kernel clears the + ## interrupt by writing the DIS back into the TSR before calling the + ## handler. The timer handler does not take any arguments. + + li %r4, PPE42_IRQ_DEC + _update_kernel_context %r4, %r3 + + _liwa %r3, TSR_DIS + mttsr %r3 + + bl __pk_timer_handler + b check_for_ext_interrupt + +program_exception_handler: + ## first check if exception was caused by an illegal 'sc' instruction + mfspr %r3, SPRN_EDR + _liw %r4, PPE42_SC_INST + cmpwbeq %r3, %r4, __sc_helper + _pk_panic PPE42_ILLEGAL_INSTRUCTION + + ## Saved SRR0 is currently pointing to the 'sc' instruction. We need to advance it + ## to the next instruction so that we don't end up in an endless loop (something + ## that the ppc sc instruction does automatically). +__sc_helper: + mfsrr0 %r4 + _lwzsd %r3, __pk_saved_sp + addi %r4, %r4, 4 + stw %r4, PK_CTX_SRR0(%r3) + + .global __pk_next_thread_resume +__pk_next_thread_resume: + + _lwzsd %r3, __pk_next_thread + _stwsd %r3, __pk_current_thread + + ## Enter the wait enabled state if the thread pointer is null + bwz %r3, __pk_idle_thread + + ## switch to the new thread stack + lwz %r1, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) + + ## load sprg0 from the stack and update the thread priority + ## in case it changed. +restore_and_update_sprg0: + _lbzsd %r31, __pk_next_priority + + PK_KERN_TRACE_ASM16("RESUME_THREAD(%d)", %r31) + + lwz %r3, PK_CTX_KERNEL_CTX(%r1) + rlwimi %r3, %r31, 24, 2, 7 + mtsprg0 %r3 + + b ctx_pop + +fit_handler: + + ## The FIT handler is user defined. By + ## convention the kernel clears the interrupt by writing the FIS back + ## into the TSR. + + li %r4, PPE42_IRQ_FIT + + _update_kernel_context %r4, %r3 + + _lwzsd %r3, __ppe42_fit_arg + + _liwa %r6, TSR_FIS + mttsr %r6 + + _lwzsd %r6, __ppe42_fit_routine + mtlr %r6 + blrl + + b check_for_ext_interrupt + +watchdog_handler: + ## Watchdog setup is described in the PK Specification. + ## The kernel clears TSR[WIS] prior to calling the handler. + + li %r4, PPE42_IRQ_WATCHDOG + + _update_kernel_context %r4, %r3 + + _liwa %r6, TSR_WIS + mttsr %r6 + + _lwzsd %r6, __ppe42_watchdog_routine + mtlr %r6 + blrl + + b check_for_ext_interrupt + + + ## Check if we can disard the interrupted context. + ## This routine expects r3, r4, lr, and cr to already be pushed. + ## It also expects r3 to hold the address of the function to jump + ## to after the interrupted context has been pushed (if necessary). + + .align 5 +ctx_check_discard: + + ## Prepare to jump to the branch function that was passed in + mtlr %r3 + + ## Check if the DISCARD_CTX bit is set in the kernel context + mfsprg0 %r3 + bb0wi %r3, PPE42_DISCARD_CTX_BIT, ctx_continue_push + +ctx_discard: + ## DISCARD_CTX bit was set. Discard stack and branch to interrupt + ## handler code + addi %r1, %r1, PK_CTX_SIZE + blr + + ## DISCARD_CTX bit was not set. Continue saving full context. + ## (r3, r4, lr, and cr have already been saved for us) and + ## r3 contains the interrupted kernel context + +ctx_continue_push: + + stvd %d5, PK_CTX_GPR5(%r1) + stvd %d7, PK_CTX_GPR7(%r1) + stvd %d9, PK_CTX_GPR9(%r1) + stvd %d28, PK_CTX_GPR28(%r1) + stvd %d30, PK_CTX_GPR30(%r1) + mfxer %r5 + mfctr %r6 + stvd %d5, PK_CTX_XER(%r1) + mfsrr0 %r7 + mfsrr1 %r8 + stvd %d7, PK_CTX_SRR0(%r1) + stw %r0, PK_CTX_GPR0(%r1) + stw %r3, PK_CTX_KERNEL_CTX(%r1) + + ## If the 'processing interrupt' bit is set then we were already + ## using the kernel stack and don't need to modify or save the current + ## stack pointer. + bb1wi %r3, PPE42_PROC_IRQ_BIT, ctx_push_completed + + ## load the pointer to the current thread control block + _lwzsd %r4, __pk_current_thread + + ## don't save the stack pointer in the thread control block + ## if the current thread was the idle thread (null pointer) + bwz %r4, switch_to_kernel_stack + + ## we interrupted a bonafide thread, so save off the stack + ## pointer + stw %r1, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r4) + +switch_to_kernel_stack: + _stwsd %r1, __pk_saved_sp + _lwzsd %r1, __pk_kernel_stack + +ctx_push_completed: + blr + +__get_ext_irq: + + ## Entry invariants: + ## 1. external interupts are disabled; + ## 2. previous context has ben saved off + ## 3. r3 contains the kernel context + ## 4. r1 points to the kernel stack + + ## This is HW Macro specific code that is responsible for finding the + ## IRQ # and storing it in r4 (phantom IRQ's are assigned a value of EXTERNAL_IRQS). + + hwmacro_get_ext_irq + + ## An active or phantom IRQ was found. + ## R3 has the context of the interrupted thread or bottom half + ## R4 has the IRQ number. + ## The IRQ is converted into a pointer to an 8-byte handler + ## structure, and the handler is dispatched. The call is made with the + ## parameters: + + ## R3 = private data ptr + ## R4 = irq + +call_external_irq_handler: + + _update_kernel_context %r4, %r3 + slwi %r3, %r4, 3 //multiply the irq# by 8 + _liw %r6, __ppe42_irq_handlers + lwzx %r5, %r6, %r3 + addi %r3, %r3, 4 + lwzx %r3, %r6, %r3 + mtlr %r5 + blrl + + ## Once the interrupt handler returns, check if any interrupts are + ## waiting and handle them now. + +check_for_ext_interrupt: + + ## Set the CTX_DISCARD bit in the kernel context so that if there is + ## an interrupt it will not bother saving the full context. + mfsprg0 %r31 + oris %r31, %r31, PPE42_DISCARD_CTX + mtsprg0 %r31 + + ###### Enable/Disable External Interrupts ##### + wrteei 1 + wrteei 0 + + ## If we made it this far, there must not be any interrupts pending. + ## If bottom half processing was interrupted we need to restore it +check_interrupted_bh: + + ## If the thread ID is 33 then the bottom half handler was interrupted + ## and needs to be restored. + extrwi %r4, %r31, 6, 2 + cmpwi %r4, 33 + beq ctx_pop_with_sprg0 + +check_for_bh: + ## if the bottom half queue is pointing to itself then the queue is + ## empty and there are no bottom halves that need processing. + _lwzsd %r4, _pk_bh_queue + lwz %r5, 0(%r4) + cmplwbeq %r4, %r5, restore_interrupted_sp + +process_bottom_halves: + ## Clear the CTX_DISCARD bit so that interrupted bottom half context + ## will be saved in case an interrupt occurs after this point. Also + ## set the thread ID to 33 so that we know to restore the bottom half + ## context that was interrupted. + rlwinm %r3, %r31, 0, 9, 1 //clear thread id + discard bit + oris %r3, %r3, 0x2100 //set thread id to 33 + mtsprg0 %r3 //set bottom half context + + ## branch to a C function that processes bottom halves + wrteei 1 + bl _pk_process_bh + wrteei 0 + + ## restore the previous kernel context (with discard bit set) + mtsprg0 %r31 + +restore_interrupted_sp: + ## restore the interrupted thread stack pointer + _lwzsd %r1, __pk_saved_sp + + ## If we are not in thread mode (i.e., we took an interrupt in an + ## interupt-only configuration of PK or after pk_initialize() but + ## before pk_start_threads) simply pop the context and RFI - in this + ## case we'll most likely be returning to main() or the non-thread-mode + ## idle thread. + +check_thread_mode: + bb0wi %r31, PPE42_THREAD_MODE_BIT, ctx_pop_with_sprg0 + + ## Check if external interrupt activated a delayed context switch. The + ## C-level code has taken care of the scheduling decisions - we simply + ## need to implement them here. +check_for_ctx_switch: + + _lwzsd %r3, __pk_delayed_switch + bwz %r3, check_for_idle_thread + + ## Clear the delayed switch flag and go to the context switch code to + ## finish the switch. + + li %r3, 0 + _stwsd %r3, __pk_delayed_switch + + b __pk_next_thread_resume + + ## check if we should switch to the wait enabled state (idle) +check_for_idle_thread: + _lwzsd %r3, __pk_current_thread + bwz %r3, __pk_idle_thread + +ctx_pop_with_sprg0: + ## we must ensure that interrupts are disabled while restoring context + ## + ## restore sprg0 from the saved context + lwz %r0, PK_CTX_KERNEL_CTX(%r1) + mtsprg0 %r0 + +#if PK_KERNEL_TRACE_ENABLE + srwi %r0, %r0, 16 + PK_KERN_TRACE_ASM16("RESUME_CONTEXT(0x%04x)", %r0) +#endif + +ctx_pop: + lwz %r0, PK_CTX_GPR0(%r1) + lvd %d7, PK_CTX_SRR0(%r1) + mtsrr1 %r8 + mtsrr0 %r7 + lvd %d5, PK_CTX_XER(%r1) + mtctr %r6 + mtxer %r5 + lvd %d30, PK_CTX_GPR30(%r1) + lvd %d28, PK_CTX_GPR28(%r1) + lvd %d9, PK_CTX_GPR9(%r1) + lvd %d7, PK_CTX_GPR7(%r1) + lvd %d5, PK_CTX_GPR5(%r1) + lvd %d3, PK_CTX_CR(%r1) + mtlr %r4 + mtcr %r3 + lvd %d3, PK_CTX_GPR3(%r1) + addi %r1, %r1, PK_CTX_SIZE + + rfi + +/// \endcond diff --git a/src/ppe/pk/ppe42/ppe42_gcc.c b/src/ppe/pk/ppe42/ppe42_gcc.c new file mode 100644 index 0000000..37674dc --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_gcc.c @@ -0,0 +1,329 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_gcc.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_gcc.h +/// \brief 32-bit PowerPC functions expected by GCC +/// +/// GCC expects certain built-in functions to be defined in the environment. +/// Since PK applications are statically linked, we must define these +/// functions ourselves to avoid a static link with the GCC libraries, which +/// would legaly require us to distribute (at least) the binary forms of PK +/// applications. +/// +/// We obviously had to look at some GCC library code to understand the +/// specifications of these routines. However, all of the code here is new - +/// no structure definitions or lines of executable code were copied from the +/// GCC sources. + +#include "pk.h" +#include "ppe42_gcc.h" + +/// A 64-bit logical right shift. +/// +/// Note that shifts with negative shift counts or shifts with shift counts +/// longer than 63 bits are undefined. + +uint64_t +__lshrdi3(uint64_t x, int i) +{ + Uint64 input, result; + + if (i == 0) { + return x; + } + + input.value = x; + + if (i >= 32) { + result.word[0] = 0; + result.word[1] = input.word[0] >> (i - 32); + } else { + result.word[0] = input.word[0] >> i; + result.word[1] = (input.word[1] >> i) | (input.word[0] << (32 - i)); + } + + return result.value; +} + + +/// A 64 bit arithmetic left shift. +/// +/// Note that shifts with negative shift counts or shifts with shift counts +/// longer than 63 bits are undefined. + +uint64_t +__ashldi3(uint64_t x, int i) +{ + Uint64 input, result; + + if (i == 0) { + return x; + } + + input.value = x; + + if (i >= 32) { + result.word[1] = 0; + result.word[0] = input.word[1] << (i - 32); + } else { + result.word[1] = input.word[1] << i; + result.word[0] = (input.word[0] << i) | (input.word[1] >> (32 - i)); + } + + return result.value ; + +} + + +/// A 64 bit arithmetic right shift. +/// +/// Note that shifts with negative shift counts or shifts with shift counts +/// longer than 63 bits are undefined. + +uint64_t +__ashrdi3(uint64_t x, int i) +{ + Int64 input, result; + + if (i == 0) { + return x; + } + + input.value = x; + + if (i >= 32) { + result.word[0] = input.word[0] >> 31; + result.word[1] = input.word[0] >> (i - 32); + } else { + result.word[0] = input.word[0] >> i; + result.word[1] = + (((uint32_t)input.word[1]) >> i) | + (input.word[0] << (32 - i)); + } + + return result.value ; + +} + + +/// 32-bit Population count + +// This is a well-known divide-and-conquer algorithm, e.g. look on Wikipedia +// under "Hamming Weight". The idea is to compute sums of adjacent bit +// segments in parallel, in place. + +int +__popcountsi2(uint32_t x) +{ + uint32_t m1 = 0x55555555; + uint32_t m2 = 0x33333333; + uint32_t m4 = 0x0f0f0f0f; + x -= (x >> 1) & m1; /* Sum pairs of bits */ + x = (x & m2) + ((x >> 2) & m2);/* Sum 4-bit segments */ + x = (x + (x >> 4)) & m4; /* Sum 8-bit segments */ + x += x >> 8; /* Sum 16-bit segments */ + return (x + (x >> 16)) & 0x3f; /* Final sum */ +} + + +/// 64-bit Population count + +int +__popcountdi2(uint64_t x) +{ + return __popcountsi2(x >> 32) + __popcountsi2(x & 0xffffffff); +} + + +// 64-bit divides +// +// For the unsigned case, note that divide by 0 returns quotient = remainder = +// 0. +// +// For the signed case, in general we perform the division on the absolute +// values and fix the signs of the quotient and remainder at the end. +// +// For the signed case, the convention in other libraries seems to be to +// ignore the case of the most-negative integer. Although it seems "wrong" to +// return the wrong answer when the right answer can be easily computed, in +// the interest of code size we follow the convention here and ignore the most +// negative integer. +// +// The assembler routine __ppe42_udiv64() assembles to ??? bytes. The full C +// routine __ppc_sdiv64 compiles to ??? bytes with the most-negative checks, +// but only ??? bytes as configured here. + +// For the signed cases, we need to handle the special case that the dividend +// or divisor is the most negative integer. +// +// If the dividend is the most negative integer, then dividing this integer by +// -1 would overflow as a positive quotient, so we set quotient and remainder +// to 0 in this case. For divide by 1, the quotient is the most negative +// integer. Otherwise we adjust the dividend by the absolute value of the +// divisor, then fix up the quotient later by adding or subtracting 1. +// +// If the divisor is the most negative integer, then the quotient is always 0 +// unless the dividend is also the most negative integer, in which case the +// quotient is 1 and the remainder is 0. +// + +uint64_t +__udivdi3(uint64_t u, uint64_t v) +{ + uint64_t quotient, remainder; + + __ppe42_udiv64(u, v, "ient, &remainder); + return quotient; +} + + +uint64_t +__umoddi3(uint64_t u, uint64_t v) +{ + uint64_t quotient, remainder; + + __ppe42_udiv64(u, v, "ient, &remainder); + return remainder; +} + + +#if 0 +#define INT64_T_MIN ((int64_t)(0x8000000000000000ull)) +#endif + +void +__ppe42_sdiv64(int64_t u, int64_t v, + int64_t *quotient, int64_t *remainder) +{ + int q_negate, r_negate; + uint64_t uu, uv; +#if 0 + int fixup = 0; +#endif + + q_negate = (u < 0) ^ (v < 0); + r_negate = (u < 0); + uu = (u < 0 ? -u : u); + uv = (v < 0 ? -v : v); + +#if 0 + if (u == INT64_T_MIN) { + if (v == -1) { + *quotient = 0; + *remainder = 0; + return; + } else if (v == 1) { + *quotient = INT64_T_MIN; + *remainder = 0; + return; + } else if (v == INT64_T_MIN) { + *quotient = 1; + *remainder = 0; + return; + } else { + fixup = 1; + u += (v < 0 ? -v : v); + } + } else if (v == INT64_T_MIN) { + *quotient = 0; + *remainder = u; + return; + } +#endif + + __ppe42_udiv64(uu, uv, (uint64_t *)quotient, (uint64_t *)remainder); + +#if 0 + if (fixup) { + *quotient += 1; + } +#endif + if (q_negate) { + *quotient = -(*quotient); + } + if (r_negate) { + *remainder = -(*remainder); + } +} + + +int64_t +__divdi3(int64_t u, int64_t v) +{ + int64_t quotient, remainder; + + __ppe42_sdiv64(u, v, "ient, &remainder); + return quotient; +} + + +int64_t +__moddi3(int64_t u, int64_t v) +{ + int64_t quotient, remainder; + + __ppe42_sdiv64(u, v, "ient, &remainder); + return remainder; +} + + +/// 64-bit unsigned compare as a function, returning 0 (<), 1 (==) or 2 (>). + +int +__ucmpdi2(uint64_t i_a, uint64_t i_b) +{ + Uint64 a, b; + int rv; + + a.value = i_a; + b.value = i_b; + + if (a.word[0] < b.word[0]) { + rv = 0; + } else if (a.word[0] > b.word[0]) { + rv = 2; + } else if (a.word[1] < b.word[1]) { + rv = 0; + } else if (a.word[1] > b.word[1]) { + rv = 2; + } else { + rv = 1; + } + + return rv; +} + + + + + + + + diff --git a/src/ppe/pk/ppe42/ppe42_gcc.h b/src/ppe/pk/ppe42/ppe42_gcc.h new file mode 100644 index 0000000..c5c16e8 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_gcc.h @@ -0,0 +1,96 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_gcc.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PPE42_GCC_H__ +#define __PPE42_GCC_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_gcc.h +/// \brief 32-bit functions expected by GCC + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + +/// A 64-bit unsigned integer type + +typedef union { + uint64_t value; + uint32_t word[2]; +} Uint64; + +/// A 64-bit signed integer type + +typedef union { + int64_t value; + int32_t word[2]; +} Int64; + +uint64_t +__lshrdi3(uint64_t x, int i); + +uint64_t +__ashldi3(uint64_t x, int i); + +uint64_t +__ashrdi3(uint64_t x, int i); + +int +__popcountsi2(uint32_t x); + +int +__popcountdi2(uint64_t x); + +/// Unsigned 64/64 bit divide, returning quotient and remainder via pointers. + +void +__ppe42_udiv64(uint64_t u, uint64_t v, uint64_t *q, uint64_t *r); + +/// Signed 64/64 bit divide, returning quotient and remainder via pointers. + +void +__ppe42_sdiv64(int64_t u, int64_t v, int64_t *q, int64_t *r); + +uint64_t +__udivdi3(uint64_t u, uint64_t v); + +int64_t +__divdi3(int64_t u, int64_t v); + +int64_t +__moddi3(int64_t u, int64_t v); + +uint64_t +__umoddi3(uint64_t u, uint64_t v); + +int +__ucmpdi2(uint64_t a, uint64_t b); + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPE42_GCC_H__ */ diff --git a/src/ppe/pk/ppe42/ppe42_init.c b/src/ppe/pk/ppe42/ppe42_init.c new file mode 100644 index 0000000..dcc660a --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_init.c @@ -0,0 +1,101 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_init.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_init.c +/// \brief PPE42 initialization routines +/// +/// The entry points in this file are routines that are typically used during +/// initialization, and their code space could be deallocated and recovered if +/// no longer needed by the application after initialization. + +#include "pk.h" +#include "pk_trace.h" + +// Note that __ppe42_system_setup() is called from the PK bootloader early +// in the initialization, at a point before the aplication has enabled +// interrupts. + +// This function is expected to be defined by the macro specific code (GPE, CME, SBE) +void __hwmacro_setup(void); + + +void +__ppe42_system_setup() +{ + //Only do this if the application hasn't provided a static table definition +#ifndef STATIC_IRQ_TABLE + PkIrqId irq; + + // Initialize the interrupt vectors. + for (irq = 0; irq < EXTERNAL_IRQS; irq++) { + __ppe42_irq_handlers[irq].handler = __ppe42_default_irq_handler; + } + + //NOTE: EXTERNAL_IRQS is the phantom interrupt assigned irq + __ppe42_irq_handlers[irq].handler = __ppe42_phantom_irq_handler; + + // Initialize special interrupt handlers + + __ppe42_fit_routine = __ppe42_default_irq_handler; + __ppe42_fit_arg = 0; + + __ppe42_watchdog_routine = __ppe42_default_irq_handler; + __ppe42_watchdog_arg = 0; + +/* + __ppe42_debug_routine = __ppe42_default_irq_handler; + __ppe42_debug_arg = 0; +*/ +#endif /*STATIC_IRQ_TABLE*/ + + //Clear all status bits in the TSR + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); + +#ifdef APPCFG_USE_EXT_TIMEBASE + //Enable the DEC interrupt and configure it to use the external dec_timer signal + mtspr(SPRN_TCR, TCR_DIE | TCR_DS); +#else + //Enable the DEC interrupt and configure it to use the internal clock signal + mtspr(SPRN_TCR, TCR_DIE); +#endif /* APPCFG_USE_EXT_TIMEBASE */ + +#if PK_TIMER_SUPPORT +#if PK_TRACE_SUPPORT +extern PkTraceBuffer g_pk_trace_buf; + //set the ppe instance id + g_pk_trace_buf.instance_id = (uint16_t)(mfspr(SPRN_PIR) & PIR_PPE_INSTANCE_MASK); +#endif /* PK_TRACE_SUPPORT */ +#endif /* PK_TIMER_SUPPORT */ + + //call macro-specific setup + __hwmacro_setup(); +} + + diff --git a/src/ppe/pk/ppe42/ppe42_irq.h b/src/ppe/pk/ppe42/ppe42_irq.h new file mode 100644 index 0000000..b86a030 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_irq.h @@ -0,0 +1,242 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_irq.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PPE42_IRQ_H__ +#define __PPE42_IRQ_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_irq.h +/// \brief PPE42 interrupt handling for PK +/// +/// Interrupt handling protocols and interrupt controller programming are +/// inherently non-portable, however PK defines APIs that may be useful among +/// different machines. +/// + + +// Define pseudo-IRQ numbers for PPE42 built-in interrupts. These numbers +// will appear in bits 16:23 of SPRG0 (__PkKernelContext) when the handlers +// are active + +#define PPE42_EXC_MACHINE_CHECK 0x50 +#define PPE42_EXC_DATA_STORAGE 0x53 +#define PPE42_EXC_INSTRUCTION_STORAGE 0x54 +#define PPE42_EXC_ALIGNMENT 0x56 +#define PPE42_EXC_PROGRAM 0x57 +#define PPE42_IRQ_DEC 0x58 +#define PPE42_IRQ_FIT 0x59 +#define PPE42_IRQ_WATCHDOG 0x5A + + +// Unhandled exceptions default to a kernel panic, but the application can +// override these definition. Note that the exception area only allocates 32 +// bytes (8 instructions) to an unhandled exception, so any redefinition +// would most likely be a branch to an application-defined handler. + +#ifndef PPE42_MACHINE_CHECK_HANDLER +#define PPE42_MACHINE_CHECK_HANDLER PK_PANIC(0x0200) +#endif + +#ifndef PPE42_DATA_STORAGE_HANDLER +#define PPE42_DATA_STORAGE_HANDLER PK_PANIC(0x0300) +#endif + +#ifndef PPE42_INSTRUCTION_STORAGE_HANDLER +#define PPE42_INSTRUCTION_STORAGE_HANDLER PK_PANIC(0x0400) +#endif + +#ifndef PPE42_ALIGNMENT_HANDLER +#define PPE42_ALIGNMENT_HANDLER PK_PANIC(0x0600) +#endif + + +//////////////////////////////////////////////////////////////////////////// +// PK API +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +/// An IRQ handler takes 2 arguments: +/// \arg \c arg - Private handler data installed by \c ssx_irq_setup() or +/// \c ssx_irq_handler_set(). +/// \arg \c irq - The IRQ id; to enable a generic handler to manipulate +/// its own interrupt status . + +typedef void (*PkIrqHandler)(void* arg, PkIrqId irq); + +/// Declare a subroutine as an IRQ handler + +#define PK_IRQ_HANDLER(f) void f(void* arg, PkIrqId irq) + +int pk_irq_setup(PkIrqId irq, + int polarity, + int trigger); + +int pk_irq_handler_set(PkIrqId irq, + PkIrqHandler handler, + void* arg); + +void pk_irq_enable(PkIrqId irq); +void pk_irq_disable(PkIrqId irq); +void pk_irq_statusclear(PkIrqId irq); + +PK_IRQ_HANDLER(__ppe42_default_irq_handler); +PK_IRQ_HANDLER(__ppe42_phantom_irq_handler); + + +int +ppe42_fit_setup(int tcr_fp, PkIrqHandler handler, void* arg); + + +/// The address of the optional FIT interrupt handler + +UNLESS__PPE42_IRQ_CORE_C__(extern) +volatile +PkIrqHandler __ppe42_fit_routine; + + +/// The private data of the optional FIT interrupt handler + +UNLESS__PPE42_IRQ_CORE_C__(extern) +volatile +void* __ppe42_fit_arg; + + +int +ppe42_watchdog_setup(int tcr_wp, int tcr_wrc, + PkIrqHandler handler, void* arg); + + +/// The address of the optional Watchdog interrupt handler + +UNLESS__PPE42_IRQ_CORE_C__(extern) +volatile +PkIrqHandler __ppe42_watchdog_routine; + + +/// The private data of the optional Watchdog interrupt handler + +UNLESS__PPE42_IRQ_CORE_C__(extern) +volatile +void* __ppe42_watchdog_arg; + + +int +ppe42_debug_setup(PkIrqHandler handler, void* arg); + + +/// The address of the optional Debug interrupt handler + +UNLESS__PPE42_IRQ_CORE_C__(extern) +volatile +PkIrqHandler __ppe42_debug_routine; + + +/// The private data of the optional Watchdog interrupt handler + +UNLESS__PPE42_IRQ_CORE_C__(extern) +volatile +void* __ppe42_debug_arg; + +#endif /* __ASSEMBLER__ */ + +// It's hard to be portable and get all of the definitions and headers in the +// correct order. We need to bring in the system IRQ header here. + +#ifdef HWMACRO_GPE +#include "gpe_irq.h" +#else +#ifdef HWMACRO_STD +#include "std_irq.h" +#endif +#endif + +/// \page ppe42_irq_macros_page PPE42 PK IRQ Assembler Macros +/// +/// + +#ifndef __ASSEMBLER__ + + +/// This structure holds the interrupt handler routine addresses and private +/// data. Assembler code assumes the given structure layout, so any changes +/// to this structure will need to be reflected down into the interrupt +/// dispatch assembler code. + +typedef struct { + PkIrqHandler handler; + void *arg; +} Ppe42IrqHandler; + + +#ifdef STATIC_IRQ_TABLE + +#define IRQ_HANDLER(func, arg) \ + {func, arg}, + +#define IRQ_HANDLER_DEFAULT \ + {__ppe42_default_irq_handler, 0}, + +#define EXTERNAL_IRQ_TABLE_END \ + {__ppe42_phantom_irq_handler, 0}\ +}; + +#define EXTERNAL_IRQ_TABLE_START \ + Ppe42IrqHandler __ppe42_irq_handlers[EXTERNAL_IRQS + 1] = \ +{ + +#else + +#define EXTERNAL_IRQ_TABLE_START + +#define IRQ_HANDLER(func, arg) + +#define IRQ_HANDLER_DEFAULT + +#define EXTERNAL_IRQ_TABLE_END + +#endif /*STATIC_IRQ_TABLE*/ + +/// Interrupt handlers for real (implemented interrupts) plus one for the phantom interrupt handler +extern Ppe42IrqHandler __ppe42_irq_handlers[EXTERNAL_IRQS + 1]; + + +/// The 'phantom interrupt' handler +/// +/// A 'phantom' interrupt occurs when the interrupt handling code in the +/// kernel is entered, but no interrupt is found pending in the controller. +/// This is considered a serious bug, as it indictates a short window +/// condition where a level-sensitive interrupt has been asserted and then +/// quickly deasserted before it can be handled. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +Ppe42IrqHandler __ppe42_phantom_irq; + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPE42_IRQ_H__ */ diff --git a/src/ppe/pk/ppe42/ppe42_irq_core.c b/src/ppe/pk/ppe42/ppe42_irq_core.c new file mode 100644 index 0000000..40460b5 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_irq_core.c @@ -0,0 +1,71 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_irq_core.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_irq_core.c +/// \brief Core IRQ routines required of any PPE42 configuration of PK +/// +/// This file is mostly only a placeholder - where 'extern inline' API +/// functions and 'extern' variables are realized. A couple of default +/// handlers are also installed here. The entry points in this file are +/// considered 'core' routines that will always be present at runtime in any +/// PK application. + +#define __PPE42_IRQ_CORE_C__ + +#include "pk.h" + +#ifndef STATIC_IRQ_TABLE +Ppe42IrqHandler __ppe42_irq_handlers[EXTERNAL_IRQS + 1]; +#endif + +/// This function is installed by default for interrupts not explicitly set up +/// by the application. These interrupts should never fire. + +void +__ppe42_default_irq_handler(void* arg, PkIrqId irq) +{ + PK_PANIC(PPE42_DEFAULT_IRQ_HANDLER); +} + + +/// This function is installed by default to handle the case that the +/// interrupt dispatch code is entered in response to an external +/// interrupt, but no interrupt is found pending in the interrupt +/// controller. This should never happen, as it would indicate that a +/// 'glitch' occurred on the external interrupt input +/// to the PPE42 core. + +void __ppe42_phantom_irq_handler(void* arg, PkIrqId irq) +{ + PK_PANIC(PPE42_PHANTOM_INTERRUPT); +} + + +#undef __PPE42_IRQ_CORE_C__ diff --git a/src/ppe/pk/ppe42/ppe42_msr.h b/src/ppe/pk/ppe42/ppe42_msr.h new file mode 100644 index 0000000..783285b --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_msr.h @@ -0,0 +1,112 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_msr.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PPE42_MSR_H__ +#define __PPE42_MSR_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_msr.h +/// \brief Everything related to the PPE42 Machine State Register +/// +/// All of the macros defined here that \e modify the MSR create a compiler +/// memory barrier that will cause GCC to flush/invalidate all memory data +/// held in registers before the macro. This is consistent with other systems, +/// e.g., the PowerPC Linux kernel, and is the safest way to define these +/// macros as it guarantess for example that kernel data structure updates +/// have completed before exiting a critical section. + +#define MSR_SEM 0x7f000000 /* SIB Error Mask */ +#define MSR_IS0 0x00800000 /* Instance-Specific Field 0 */ +#define MSR_SIBRC 0x00700000 /* Last SIB return code */ +#define MSR_LP 0x00080000 /* Low Priority */ +#define MSR_WE 0x00040000 /* Wait State Enable */ +#define MSR_IS1 0x00020000 /* Instance-Specific Field 1 */ +#define MSR_UIE 0x00010000 /* Unmaskable Interrupt Enable */ +#define MSR_EE 0x00008000 /* External Interrupt Enable */ +#define MSR_ME 0x00001000 /* Machine Check Exception Enable */ +#define MSR_IPE 0x00000100 /* Imprecise Mode Enable */ +#define MSR_SIBRCA 0x000000ff /* SIB Return Code Accumulator */ + +//#define MSR_CE_BIT 14 +#define MSR_EE_BIT 16 +//#define MSR_IR_BIT 26 +//#define MSR_DR_BIT 27 + + +#define MSR_SEM_START_BIT 1 +#define MSR_SEM_LEN 7 +#define MSR_SIBRC_START_BIT 9 +#define MSR_SIBRC_LEN 3 + + +#ifndef __ASSEMBLER__ + +/// Move From MSR + +#define mfmsr() \ + ({uint32_t __msr; \ + asm volatile ("mfmsr %0" : "=r" (__msr)); \ + __msr;}) + + +/// Move to MSR + +#define mtmsr(value) \ + asm volatile ("mtmsr %0" : : "r" (value) : "memory") + + +/// Read-Modify-Write the MSR with OR (Set MSR bits). This operation is only +/// guaranteed atomic in a critical section. + +#define or_msr(x) \ + mtmsr(mfmsr() | (x)) + + +/// Read-Modify-Write the MSR with AND complement (Clear MSR bits). This +/// operation is only guaranteed atomic in a critical section. + +#define andc_msr(x) \ + mtmsr(mfmsr() & ~(x)) + + +/// Write MSR[EE] with an immediate value (0/1) +/// +/// Note that the immediate value \a i must be a compile-time constant. + +#define wrteei(i) \ + asm volatile ("wrteei %0" : : "i" (i) : "memory") + + +/// Write MSR[EE] from the EE bit of another MSR + +#define wrtee(other_msr) \ + asm volatile ("wrtee %0" : : "r" (other_msr) : "memory") + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPE42_MSR_H__ */ diff --git a/src/ppe/pk/ppe42/ppe42_scom.c b/src/ppe/pk/ppe42/ppe42_scom.c new file mode 100755 index 0000000..20da4df --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_scom.c @@ -0,0 +1,101 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_scom.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_scom.c +/// \brief Lowest level PK SCOM definitions. +/// +/// Currently these SCOM functions are only optimized for functionality, not +/// speed. Speed optimization will be done when we have full compiler support +/// for the low-level stvd and lvd SCOM OPs. +/// +/// A FAPI-lite SCOM can call these PK SCOM functions. +/// +/// Comment: +/// - No need to poll for SCOM completion, nor return error code of SCOM fails. +/// A SCOM fail will cause the GPE to hang if configured to do so. But do we +/// necessarily have to do this? Wouldn't a gentle recovery from a SCOM fail +/// be preferred? + +#include "pk.h" +#include "ppe42_scom.h" +#include "ppe42_msr.h" + + +uint32_t putscom_abs(const uint32_t i_address, uint64_t *i_data) +{ + + // Perform the Store Virtual Double instruction + PPE_STVD(i_address, &i_data); + + // Get the MSR[SIBRC] as the return code + uint32_t rc = mfmsr(); + rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); + return (rc); + +} + +uint32_t _putscom( uint32_t i_chiplet_id, uint32_t i_address, uint64_t *i_data) +{ + + // Perform the Store Virtual Double Index instruction + PPE_STVDX(i_chiplet_id, i_address, &i_data); + + // Get the MSR[SIBRC] as the return code + uint32_t rc = mfmsr(); + rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); + return (rc); + +} + +uint32_t getscom_abs( const uint32_t i_address, uint64_t *o_data) +{ + + // Perform the Load Virtual Double instruction + PPE_LVD(i_address, &o_data); + + // Get the MSR[SIBRC] as the return code + uint32_t rc = mfmsr(); + rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); + return (rc); +} + + +uint32_t _getscom( const uint32_t i_chiplet_id, const uint32_t i_address, uint64_t *o_data) +{ + + // Perform the Load Virtual Double Index instruction + PPE_LVDX(i_chiplet_id, i_address, &o_data); + + // Get the MSR[SIBRC] as the return code + uint32_t rc = mfmsr(); + rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); + return (rc); + +} diff --git a/src/ppe/pk/ppe42/ppe42_scom.h b/src/ppe/pk/ppe42/ppe42_scom.h new file mode 100755 index 0000000..42bc87a --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_scom.h @@ -0,0 +1,160 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_scom.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_scom.h +/// \brief Include file for PK SCOMs +/// + +#ifndef __PK_SCOM_H__ +#define __PK_SCOM_H__ + +/// SCOM operations return non-zero error codes that may or may not indicate +/// an actual error, depending on which SCOM is begin accessed. This error +/// code will appear in the MSR[SIBRC] field, bits[9:11] right after the +/// SCOM OP returns. The error code value increases with the severity of the +/// error. +#define PCB_ERROR_NONE 0 +#define PCB_ERROR_RESOURCE_OCCUPIED 1 +#define PCB_ERROR_CHIPLET_OFFLINE 2 +#define PCB_ERROR_PARTIAL_GOOD 3 +#define PCB_ERROR_ADDRESS_ERROR 4 +#define PCB_ERROR_CLOCK_ERROR 5 +#define PCB_ERROR_PACKET_ERROR 6 +#define PCB_ERROR_TIMEOUT 7 + +#ifdef __cplusplus +extern "C" { +#endif + + +/// PPE Load Virtual Double operation +#define PPE_LVD(_m_address, _m_data) \ +asm volatile \ + ( \ + "lvd %[data], 0(%[address]) \n" \ + : [data]"=&r"(*_m_data) \ + : "[data]"(*_m_data), \ + [address]"r"(_m_address) \ + ); + + +// PPE Store Virtual Double operation +#define PPE_STVD(_m_address, _m_data) \ +asm volatile \ + ( \ + "stvd %[data], 0(%[address]) \n" \ + : [data]"=&r"(*_m_data) \ + : "[data]"(*_m_data), \ + [address]"r"(_m_address) \ + : "memory" \ + ); + +/// PPE Load Virtual Double Indexed operation +#define PPE_LVDX(_m_base, _m_offset, _m_data) \ +asm volatile \ + ( \ + "lvdx %[data], %[base], %[offset] \n" \ + : [data]"=&r"(*_m_data) \ + : "[data]"(*_m_data), \ + [base]"r"(_m_base), \ + [offset]"r"(_m_offset) \ + ); + + +// PPE Store Virtual Double Indexed operation +#define PPE_STVDX(_m_base, _m_offset, _m_data) \ +asm volatile \ + ( \ + "stvdx %[data], %[base], %[offset] \n" \ + : [data]"=&r"(*_m_data) \ + : "[data]"(*_m_data), \ + [base]"r"(_m_base), \ + [offset]"r"(_m_offset) \ + : "memory" \ + ); + +#define PPE_MFMSR(_m_data) \ +asm volatile \ + ( \ + "mfmsr %[data] \n" \ + : [data]"=&r"(*_m_data) \ + : "[data]"(*_m_data) \ + ); + +/// @brief putscom with absolute address +/// @param [in] i_address Fully formed SCOM address +/// @param [in] i_data Pointer to uint64_t data to be written. A pointer is used +/// to optimize the underlying hardware execution +/// +/// @retval On PPE42 platform, unmasked errors will take machine check interrupts +uint32_t putscom_abs(const uint32_t i_address, uint64_t *i_data); + +/// @brief getscom with absolute address +/// @param [in] i_address Fully formed SCOM address +/// @param [in] *o_data Pointer to uint64_t data read +/// +/// @retval On PPE42 platform, unmasked errors will take machine check interrupts + +uint32_t getscom_abs( const uint32_t i_address, uint64_t *o_data); + +/// @brief Implementation of PPE putscom functionality +/// @param [in] i_chiplet Chiplet ID (@todo Should only be right justified) +/// @param [in] i_address Base SCOM address +/// @param [in] i_data Pointer to uint64_t data to be written. A pointer is used +/// to optimize the underlying hardware execution +/// +/// @retval On PPE42 platform, unmasked errors will take machine check interrupts +uint32_t _putscom( const uint32_t i_chiplet, const uint32_t i_address, uint64_t *i_data); + + +/// @brief Implementation of PPE getscom functionality +/// @param [in] i_chiplet Chiplet ID (@todo Should only be right justified) +/// @param [in] i_address Base SCOM address +/// @param [in] i_data Pointer to uint64_t data read +/// +/// @retval On PPE42 platform, unmasked errors will take machine check interrupts +uint32_t _getscom( uint32_t i_chiplet, uint32_t i_address, uint64_t *o_data); + +extern inline uint32_t putscom(const uint32_t i_chiplet, const uint32_t i_address, uint64_t *i_data) +{ + return _putscom(i_chiplet, i_address, i_data); +} + + +extern inline uint32_t getscom(const uint32_t i_chiplet, const uint32_t i_address, uint64_t *o_data) +{ + return _getscom(i_chiplet, i_address, o_data); +} + +#ifdef __cplusplus +} // extern C +#endif + +#endif // __PK_SCOM_H__ diff --git a/src/ppe/pk/ppe42/ppe42_spr.h b/src/ppe/pk/ppe42/ppe42_spr.h new file mode 100644 index 0000000..e53a5d5 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_spr.h @@ -0,0 +1,197 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_spr.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PPE42_SPR_H__ +#define __PPE42_SPR_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_spr.h +/// \brief Everything related to PPE42-specific SPRs + +/// \defgroup ppe42_sprs PPE42 SPRs +/// +/// These are the documented SPRs of the PPE42. Most of these SPRs are +/// available in RISCWatch and eCmd using the defined names (minus SPRN_). In +/// some cases RISCWatch/eCMD use different names, which appear in square +/// brackets in the brief comments for each register. RISCWatch/eCMD also +/// allow CR, MSR and IAR (Instruction Address Register) to be accessed as +/// SPRs. +/// +/// @{ + + #define SPRN_XER 0x001 /// Fixed-point exception register + #define SPRN_LR 0x008 /// Link register + #define SPRN_CTR 0x009 /// Count register + #define SPRN_DEC 0x016 /// Decrementer + #define SPRN_SRR0 0x01a /// Save/restore register 0 + #define SPRN_SRR1 0x01b /// Save/restore register 1 + #define SPRN_EDR 0x03d /// Error Data Register + #define SPRN_ISR 0x03e /// Interrupt Status Register + #define SPRN_IVPR 0x03f /// Interrupt Vector Prefix Register + #define SPRN_SPRG0 0x110 /// SPR general register 0 + #define SPRN_PIR 0x11e /// Processor Identification Register + #define SPRN_PVR 0x11f /// Processor version register + #define SPRN_DBCR 0x134 /// Debug Control Register + #define SPRN_DACR 0x13c /// Debug Address Compare Register + #define SPRN_TSR 0x150 /// Timer Status Register + #define SPRN_TCR 0x154 /// Timer Control Register + +/* DBCR - Debug Control Register */ + +#define DBCR_RST 0x30000000 /* Reset: 01=Soft Reset, 10=Hard Reset, 11=Halt */ +#define DBCR_TRAP 0x01000000 /* Trap Instruction Enable */ +#define DBCR_IACE 0x00800000 /* Instruction Address Compare Enable */ +#define DBCR_DACE 0x000c0000 /* Data Address Compare Enable: 01=store, 10=load, 11=both */ + +/* TCR - Timer Control Register */ + +#define TCR_WP_MASK 0xc0000000 /* Watchdog timer select bits */ +#define TCR_WP_0 0x00000000 /* WDT uses timer 0 */ +#define TCR_WP_1 0x40000000 /* WDT uses timer 1 */ +#define TCR_WP_2 0x80000000 /* WDT uses timer 2 */ +#define TCR_WP_3 0xc0000000 /* WDT uses timer 3 */ +#define TCR_WRC_MASK 0x30000000 /* Watchdog Reset Control mask */ +#define TCR_WRC_NONE 0x00000000 /* WDT results in no action */ +#define TCR_WRC_SOFT 0x10000000 /* WDT results in Soft reset */ +#define TCR_WRC_HARD 0x20000000 /* WDT results in Hard reset */ +#define TCR_WRC_HALT 0x30000000 /* WDT results in Halt */ +#define TCR_WIE 0x08000000 /* Watchdog Interrupt Enable */ +#define TCR_DIE 0x04000000 /* Decrementer Interrupt Enable */ +#define TCR_FP_MASK 0x03000000 /* FIT Timer Select bits*/ +#define TCR_FP_0 0x00000000 /* FIT uses timer 0 */ +#define TCR_FP_1 0x01000000 /* FIT uses timer 1 */ +#define TCR_FP_2 0x02000000 /* FIT uses timer 2 */ +#define TCR_FP_3 0x03000000 /* FIT uses timer 3 */ +#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */ +#define TCR_DS 0x00400000 /* Decrementer timer select: 0=every cycle, 1=use dec_timer input signal */ + +#ifndef __ASSEMBLER__ + +typedef union { + uint32_t value; + struct { + unsigned int wp : 2; + unsigned int wrc : 2; + unsigned int wie : 1; + unsigned int die : 1; + unsigned int fp : 2; + unsigned int fie : 1; + unsigned int ds : 1; + unsigned int reserved : 22; + } fields; +} Ppe42TCR; + +#endif /* __ASSEMBLER__ */ + +/* TSR - Timer Status Register */ + +#define TSR_ENW 0x80000000 /* Enable Next Watchdog */ +#define TSR_WIS 0x40000000 /* Watchdog Interrupt Status */ +#define TSR_WRS_MASK 0x30000000 /* Watchdog Reset Status */ +#define TSR_WRS_NONE 0x00000000 /* No watchdog reset has occurred */ +#define TSR_WRS_SOFT 0x10000000 /* Soft reset was forced by the watchdog */ +#define TSR_WRS_HARD 0x20000000 /* Hard reset was forced by the watchdog */ +#define TSR_WRS_HALT 0x30000000 /* Halt was forced by the watchdog */ +#define TSR_DIS 0x08000000 /* Decrementer Interrupt Status */ +#define TSR_FIS 0x04000000 /* FIT Interrupt Status */ + +/* PIR - Processor Identification Register */ +#define PIR_PPE_TYPE_MASK 0x000000E0 +#define PIR_PPE_TYPE_GPE 0x00000020 +#define PIR_PPE_TYPE_CME 0x00000040 +#define PIR_PPE_INSTANCE_MASK 0x0000001F + +#ifndef __ASSEMBLER__ + +/// Move From SPR +/// +/// Note that \a sprn must be a compile-time constant. + +#define mfspr(sprn) \ + ({uint32_t __value; \ + asm volatile ("mfspr %0, %1" : "=r" (__value) : "i" (sprn)); \ + __value;}) + + +/// Move to SPR +/// +/// Note that \a sprn must be a compile-time constant. + +#define mtspr(sprn, value) \ + ({uint32_t __value = (value); \ + asm volatile ("mtspr %0, %1" : : "i" (sprn), "r" (__value)); \ + }) + + +/// Read-Modify-Write an SPR with OR (Set SPR bits) +/// +/// Note that \a sprn must be a compile-time constant. This operation is only +/// guaranteed atomic in a critical section. + +#define or_spr(sprn, x) \ + mtspr(sprn, mfspr(sprn) | (x)) + + +/// Read-Modify-Write an SPR with AND complement (Clear SPR bits) +/// +/// Note that \a sprn must be a compile-time constant. This operation is only +/// guaranteed atomic in a critical section. + +#define andc_spr(sprn, x) \ + mtspr(sprn, mfspr(sprn) & ~(x)) + +#endif /* __ASSEMBLER__ */ + +#ifdef __ASSEMBLER__ + + /// \cond + + // Use this macro to define new mt<spr> and mf<spr> instructions that + // may not exist in the assembler. + + .macro _sprinstrs, name, num + .macro mt\name, reg + mtspr \num, \reg + .endm + .macro mf\name, reg + mfspr \reg, \num + .endm + .endm + + _sprinstrs dbcr, SPRN_DBCR + _sprinstrs tcr, SPRN_TCR + _sprinstrs tsr, SPRN_TSR + _sprinstrs sprg0, SPRN_SPRG0 + _sprinstrs ivpr, SPRN_IVPR + _sprinstrs dec, SPRN_DEC + + /// \endcond + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPE42_SPR_H__ */ diff --git a/src/ppe/pk/ppe42/ppe42_thread_init.S b/src/ppe/pk/ppe42/ppe42_thread_init.S new file mode 100644 index 0000000..14fb3d0 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_thread_init.S @@ -0,0 +1,134 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/ppe42/ppe42_thread_init.S $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +/// \file ppe42_thread_init.S +/// \brief PPE42-specific thread initialization +/// +/// The entry points in this file are routines that are typically used during +/// initialization, and their code space could be deallocated and recovered if +/// no longer needed by the application after initialization. + + .nolist +#include "pk.h" + .list + +/// \fn void __pk_thread_context_initialize(PkThread *thread, PkThreadRoutine thread_routine, void *private) +/// \brief Create the initial thread context on the stack +/// +/// The non-reserved GPRs are prepatterned with 0x0000\<rn\>\<rn\> where \<rn\> is +/// the register number (as decimal). The initial context is set up with the +/// thread running in the default machine context, and when the thread is +/// switched in it will begin executing at the entry point of the thread +/// routine with the \c private parameter in R3. The LR is initialized such +/// that when the thread returns, it will return to the entry point of \c +/// pk_complete(). +#ifdef DOXYGEN_ONLY +void +__pk_thread_context_initialize(PkThread *thread, + PkThreadRoutine thread_routine, + void *private); +#endif +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \cond + + .global_function __pk_thread_context_initialize + +__pk_thread_context_initialize: + + ## R3 = thread (param) + ## R4 = thread_routine (param) + ## R5 = private (param) + ## R6 = thread stack pointer (computed) + ## R7 = scratch + + .macro _gpr_init, prefix, reg, val + li %r7, \val + stw %r7, \prefix\reg(%r6) + .endm + + ## Initialize volatile context on the thread stack. The CR is cleared, + ## the LR = pk_complete(), R3 has the private parameter. + + lwz %r6, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) + + stwu %r6, -PK_CTX_SIZE(%r6) + + li %r7, 0 + stw %r7, PK_CTX_CR(%r6) + + _liw %r7, pk_complete + stw %r7, PK_CTX_LR(%r6) + + stw %r5, PK_CTX_GPR3(%r6) + + _gpr_init PK_CTX_GPR, 4, 0x0404 + _gpr_init PK_CTX_GPR, 5, 0x0505 + _gpr_init PK_CTX_GPR, 6, 0x0606 + + ## XER and CTR are clear, SRR0 = thread_routine, SRR1 = default machine + ## context. + + li %r7, 0 + stw %r7, PK_CTX_XER(%r6) + stw %r7, PK_CTX_CTR(%r6) + + stw %r4, PK_CTX_SRR0(%r6) + + _lwzsd %r7, __pk_thread_machine_context_default + stw %r7, PK_CTX_SRR1(%r6) + + _gpr_init PK_CTX_GPR, 0, 0x0000 + _gpr_init PK_CTX_GPR, 7, 0x0707 + _gpr_init PK_CTX_GPR, 8, 0x0808 + _gpr_init PK_CTX_GPR, 9, 0x0909 + _gpr_init PK_CTX_GPR, 10, 0x1010 + + ## Initialize the non-volatile context on the thread stack. + + _gpr_init PK_CTX_GPR, 28, 0x2828 + _gpr_init PK_CTX_GPR, 29, 0x2929 + _gpr_init PK_CTX_GPR, 30, 0x3030 + _gpr_init PK_CTX_GPR, 31, 0x3131 + + ## Initialize the kernel context on the thread stack. + ## Note: Thread priority is set later each time the thread is + ## resumed. + + lis %r7, PPE42_THREAD_MODE + stw %r7, PK_CTX_KERNEL_CTX(%r6) + + ## Initialization is done - the stack pointer is stored back in the + ## thread. + + stw %r6, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) + blr + + .epilogue __pk_thread_context_initialize + +/// \endcond diff --git a/src/ppe/pk/ppe42/ppe42_timebase.S b/src/ppe/pk/ppe42/ppe42_timebase.S new file mode 100644 index 0000000..a0884e6 --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_timebase.S @@ -0,0 +1,140 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_timebase.S $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/// \file ppe42_timebase.S +/// \brief PPE42-specific 64 bit timebase emulation +/// + .nolist +#include "pk.h" + .list + +/// \fn PkTimebase pk_timebase_get(void) +/// \brief Returns a 64 bit timebase +/// +#ifdef DOXYGEN_ONLY +PkTimebase +pk_timebase_get(void); +#endif +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \cond + .global ppe42_64bit_timebase + .global ppe42_tb_data + .global_function pk_timebase_get + +#ifndef APPCFG_USE_EXT_TIMEBASE + + /// Note that it is ok to use this function in a fast interrupt + /// context + .align 5 + .global_function pk_timebase32_get +pk_timebase32_get: + + //load the decrementer start time and change tag + lvd %r4, ppe42_tb_data@sda21(0) + + //load the lower 32 bits of the 64bit timebase accumulator + lwz %r3, ppe42_64bit_timebase+4@sda21(0) + + //load the current decrementer value + mfdec %r0 + + //load the change tag again (should already be in the cache) + lwz %r6, ppe42_tb_data+4@sda21(0) + + //loop until the change tag is the same (typically should be same) + cmplwbne %r5, %r6, pk_timebase32_get + + //calculate how much time has passed since the decrementer was started and store in r6 + subf %r5, %r0, %r4 + + //add the 32bit difference to our 32bit timebase accumulator + add %r3, %r5, %r3 + + blr + + +/// Use the DEC for our timebase until we have a real timebase register (uses +/// 9 instructions). +/// Note: It is not ok to use this function in a fast interrupt context due to +/// its use of r7 + .align 5 +pk_timebase_get: + + //load the decrementer start time and change tag + lvd %r5, ppe42_tb_data@sda21(0) + + //load 64bit timebase accumulator + lvd %r3, ppe42_64bit_timebase@sda21(0) + + + //load the current decrementer value + mfdec %r0 + + //load the change tag again (should already be in the cache) + lwz %r7, ppe42_tb_data+4@sda21(0) + + //loop until the change tag is the same + cmplwbne %r6, %r7, pk_timebase_get + + //calculate how much time has passed since the decrementer was started and store in r6 + subf %r6, %r0, %r5 + + //add the 32bit difference to the 64bit timebase accumulator + addc %r4, %r6, %r4 + addze %r3, %r3 + + blr + +//enable this once we have a local timebase register in the model +#else + +// use the local timebase register to keep more accurate time with just 6 instructions +// in the common case and 7 otherwise. + .align 5 +pk_timebase_get: + + //load the 64bit timebase accumulator + lvd r3, ppe42_64bit_timebase@sda21(0) + + //read the local timebase register (2 instructions) + _pk_timebase32_get r5, r5 + + //increment the upper 32 bits if the lower 32 bits have flipped + cmplwbge r5, r4, update_lower_32 + + //increment the upper 32 bits + addi r3, r3, 1 + +update_lower_32: + //replace the lower 32bits with what we read from the local timebase register + mr r4, r5 + + blr +#endif /* APPCFG_USE_EXT_TIMEBASE */ +/// \endcond diff --git a/src/ppe/pk/std/Makefile b/src/ppe/pk/std/Makefile new file mode 100644 index 0000000..443430f --- /dev/null +++ b/src/ppe/pk/std/Makefile @@ -0,0 +1,74 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/std/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# This Makefile compiles all of the PK code required for the STD (standard PPE) port +# of PK. See the "pk.mk" file in this directory. + +#all generated files from this makefile will end up in obj/$(IMAGE_NAME)/pk +export SUB_OBJDIR = /pk + +include img_defs.mk +include pkstdfiles.mk + +ifeq "$(PK_TIMER_SUPPORT)" "1" +STD_OBJECTS += ${STD-TIMER-C-SOURCES:.c=.o} ${STD-TIMER-S-SOURCES:.S=.o} +endif + +ifeq "$(PK_THREAD_SUPPORT)" "1" +STD_OBJECTS += ${STD-THREAD-C-SOURCES:.c=.o} ${STD-THREAD-S-SOURCES:.S=.o} +endif + +ifeq "$(STD_ASYNC_SUPPORT)" "1" +STD_OBJECTS += ${STD-ASYNC-C-SOURCES:.c=.o} ${STD-ASYNC-S-SOURCES:.S=.o} +endif + +OBJS := $(addprefix $(OBJDIR)/, $(STD_OBJECTS)) + +libpk.a: kernel ppe42 trace std + $(AR) crs $(OBJDIR)/libpk.a $(OBJDIR)/*.o + +.PHONY: clean std kernel ppe42 trace +std: $(OBJS) + +trace: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../trace + +kernel: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../kernel + +ppe42: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../ppe42 + + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +clean: + rm -fr $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/pk/std/pk_port.h b/src/ppe/pk/std/pk_port.h new file mode 100644 index 0000000..2ed0d3d --- /dev/null +++ b/src/ppe/pk/std/pk_port.h @@ -0,0 +1,41 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/std/pk_port.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_PORT_H__ +#define __PK_PORT_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_port.h +/// \brief The top-level standard PPE environment header for PK. + +#define HWMACRO_STD + +#include "ppe42.h" +#include "std_timebase.h" + +#endif /* __PK_PORT_H__ */ diff --git a/src/ppe/pk/std/pkstdfiles.mk b/src/ppe/pk/std/pkstdfiles.mk new file mode 100644 index 0000000..3f9a731 --- /dev/null +++ b/src/ppe/pk/std/pkstdfiles.mk @@ -0,0 +1,57 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/std/pkstdfiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file pkstdfiles.mk +# +# @brief mk for including std object files +# +# @page ChangeLogs Change Logs +# @section pkstdfiles.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# Object Files +########################################################################## + +STD-C-SOURCES = std_init.c std_irq_init.c +STD-S-SOURCES = + +STD-TIMER-C-SOURCES = +STD-TIMER-S-SOURCES = + +STD-THREAD-C-SOURCES = +STD-THREAD-S-SOURCES = + +STD-ASYNC-C-SOURCES = +STD-ASYNC-S-SOURCES = + +STD_OBJECTS += $(STD-C-SOURCES:.c=.o) $(STD-S-SOURCES:.S=.o) + diff --git a/src/ppe/pk/std/std.h b/src/ppe/pk/std/std.h new file mode 100644 index 0000000..b20f6ae --- /dev/null +++ b/src/ppe/pk/std/std.h @@ -0,0 +1,44 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/std/std.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __STD_H__ +#define __STD_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp.h +/// \brief The STD environment for PK. + +#ifndef HWMACRO_STD +#define HWMACRO_STD +#include "ppe42.h" +#endif + +#include "std_register_addresses.h" +#include "std_common.h" + +#endif /* __STD_H__ */ diff --git a/src/ppe/pk/std/std_common.h b/src/ppe/pk/std/std_common.h new file mode 100644 index 0000000..e709f67 --- /dev/null +++ b/src/ppe/pk/std/std_common.h @@ -0,0 +1,78 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/std/std_common.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __STD_COMMON_H__ +#define __STD_COMMON_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file cme_common.h +/// \brief Common header for standard PPE's +/// + +#ifndef __ASSEMBLER__ +#include <stdint.h> +#endif + +//#include "cmehw_interrupts.h" +#include "pk.h" +#include "std_irq_config.h" + +#ifdef __ASSEMBLER__ +/// This macro contains standard PPE code for determining what IRQ caused the +/// external exception handler to be invoked by the PPE + +/// Check for interrupts pending in the interrupt status register while the IRQ +/// is computed. The IRQ is expected to be stored in r4. If no IRQ is +/// pending then load the phantom irq # (EXTERNAL_IRQS). +/// +/// r1, r2, r3, and r13 must not be modified. All other registers may be used. +/// + .macro hwmacro_get_ext_irq + + _lvdg d5, STD_LCL_EISTR #load the 64bit interrupt status into d5 + cntlzw r4, r5 + cmpwible r4, 31, call_external_irq_handler #branch if irq is lt or eq to 31 + + ## No IRQ pending in r5. Try r6. + ## Note: irq # will be 64 (phantom irq) if no bits were set in either register + + cntlzw r4, r6 + addi r4, r4, 32 + + .endm + +/// Redirect the .hwmacro_irq_cfg_bitmaps macro to call our standard PPE implementation +/// This is called from the ppe42_exceptions.S file. + .macro .hwmacro_irq_cfg_bitmaps + .std_irq_cfg_bitmaps + .endm + +#endif /* __ASSEMBLER__ */ + +#endif /* __STD_COMMON_H__ */ diff --git a/src/ppe/pk/std/std_init.c b/src/ppe/pk/std/std_init.c new file mode 100644 index 0000000..8d9bb12 --- /dev/null +++ b/src/ppe/pk/std/std_init.c @@ -0,0 +1,74 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/std/std_init.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file std_init.c +/// \brief PK initialization for a standard PPE. +/// +/// The entry points in this routine are used during initialization. This +/// code space can be deallocated and reassigned after application +/// initialization if required. + +#include "pk.h" + +/// Standard PPE environment initial setup. +/// +/// This is setup common to all standard PPE Macro applications. This setup takes place +/// during boot, before main() is called. + +void +__hwmacro_setup(void) +{ + //mask all interrupts + out64(STD_LCL_EIMR_OR, 0xffffffffffffffffull); + + //Set all interrupts to active low, level sensitive by default + out64(STD_LCL_EIPR_CLR, 0xffffffffffffffffull); + out64(STD_LCL_EITR_CLR, 0xffffffffffffffffull); + + //set up the configured type + out64(STD_LCL_EITR_OR, g_ext_irqs_type); + + //set up the configured polarity + out64(STD_LCL_EIPR_OR, g_ext_irqs_polarity); + + //clear the status of all active-high interrupts (has no affect on + //level sensitive interrupts) + out64(STD_LCL_EISR_CLR, g_ext_irqs_polarity); + + //clear the status of all active-low interrupts (has no affect on + //level sensitive interrupts) + out64(STD_LCL_EISR_OR, ~g_ext_irqs_polarity); + + //unmask the interrupts that are to be enabled by default + out64(STD_LCL_EIMR_CLR, g_ext_irqs_enable); + + //wait for the last operation to complete + sync(); +} diff --git a/src/ppe/pk/std/std_irq.h b/src/ppe/pk/std/std_irq.h new file mode 100644 index 0000000..e30a219 --- /dev/null +++ b/src/ppe/pk/std/std_irq.h @@ -0,0 +1,110 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/std/std_irq.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __STD_IRQ_H__ +#define __STD_IRQ_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file occhw_irq.h +/// \brief Standard PPE Externnal Interrupt handling for PK +/// +/// The standard PPE interrupt controller supports a maximum of 64 interrupts with +/// simple OR combining of the interrupt signals. +/// +/// The standard PPE interrupt controller allows interrupt status to be set directly by +/// software. It contains a 'mask' register, unlike most 405 interrupt +/// controllers that have an 'enable' register. The standard PPE mask and status +/// registers also have atomic CLR/OR function so that it is never necessary +/// to enter a critical section to enable/disable/clear interrupts and +/// interrupt status. + +#include "std_common.h" +#include "std_register_addresses.h" +#include "ppe42.h" + +#ifndef __ASSEMBLER__ + +/// Enable an interrupt by clearing the mask bit. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_enable(PkIrqId irq) +{ + out64(STD_LCL_EIMR_CLR, STD_IRQ_MASK64(irq)); +} + + +/// Disable an interrupt by setting the mask bit. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_disable(PkIrqId irq) +{ + out64(STD_LCL_EIMR_OR, STD_IRQ_MASK64(irq)); +} + + +/// Clear interrupt status with an CLR mask. Only meaningful for +/// edge-triggered interrupts. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_status_clear(PkIrqId irq) +{ + out64(STD_LCL_EISR_CLR, STD_IRQ_MASK64(irq)); +} + + +/// Get IRQ status as a 0 or non-0 integer + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline int +pk_irq_status_get(PkIrqId irq) +{ + return (in64(STD_LCL_EISR) & STD_IRQ_MASK64(irq)) != 0; +} + + +/// Set or clear interrupt status explicitly. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_status_set(PkIrqId irq, int value) +{ + if (value) { + out64(STD_LCL_EISR_OR, STD_IRQ_MASK64(irq)); + } else { + out64(STD_LCL_EISR_CLR, STD_IRQ_MASK64(irq)); + } +} + + +#endif /* __ASSEMBLER__ */ + +#endif /* __STD_IRQ_H__ */ diff --git a/src/ppe/pk/std/std_irq_config.h b/src/ppe/pk/std/std_irq_config.h new file mode 100644 index 0000000..5044b42 --- /dev/null +++ b/src/ppe/pk/std/std_irq_config.h @@ -0,0 +1,165 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/std/std_irq_config.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __STD_IRQ_CONFIG_H__ +#define __STD_IRQ_CONFIG_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file std_irq_config.h +/// \brief Contains data and macros pertaining to external interrupt +/// configuration for a standard PPE. +/// + +/// This constant is used to define the size of the table of interrupt handler +/// structures as well as a limit for error checking. +#define EXTERNAL_IRQS 64 + +// Standard interrupt type values (level or edge) +#define STD_IRQ_TYPE_LEVEL 0 +#define STD_IRQ_TYPE_EDGE 1 + +// Standard interrupt polarity values (high or low, rising falling) +#define STD_IRQ_POLARITY_LO 0 +#define STD_IRQ_POLARITY_FALLING 0 +#define STD_IRQ_POLARITY_HI 1 +#define STD_IRQ_POLARITY_RISING 1 + +// Standard interrupt mask values (masked or enabled) +#define STD_IRQ_MASKED 0 +#define STD_IRQ_ENABLED 1 + +// Fail to compile if the application does not define this +#ifndef APPCFG_EXT_IRQS_CONFIG +#error "APPCFG_EXT_IRQS_CONFIG must be defined in pk_app_cfg.h" +#endif + +// Fail to compile if the application does not define this +#ifndef APPCFG_IRQ_INVALID_MASK +#error "APPCFG_IRQ_INVALID_MASK must be defined in pk_app_cfg.h" +#endif + +#ifndef __ASSEMBLER__ + +/// This expression recognizes only those IRQ numbers that have named +/// (non-reserved) interrupts in the standard PPE interrupt controller. +#define STD_IRQ_VALID(irq) \ + ({unsigned __irq = (unsigned)(irq); \ + ((__irq < EXTERNAL_IRQS) && \ + ((STD_IRQ_MASK64(__irq) & \ + APPCFG_IRQ_INVALID_MASK) == 0));}) + +/// This is a 64-bit mask, with big-endian bit 'irq' set. +#define STD_IRQ_MASK64(irq) (0x8000000000000000ull >> (irq)) + +#else + +//Untyped assembler version of STD_IRQ_MASK64 +#define STD_IRQ_MASK64(irq) (0x8000000000000000 >> (irq)) + +#endif /* __ASSEMBLER__ */ + +#ifndef __ASSEMBLER__ +/// These globals are statically initialized elsewhere +extern uint64_t g_ext_irqs_type; +extern uint64_t g_ext_irqs_valid; +extern uint64_t g_ext_irqs_polarity; +extern uint64_t g_ext_irqs_enable; +#endif + +#ifdef __ASSEMBLER__ +/// These macros aid in the initialization of the external interrupt globals. I would +/// prefer to use CPP macros, but they don't support recursive macros which I use to +/// convert the variable number of interrupts that a processor can control into static +/// bitmaps used by __hwmacro_setup() at runtime. + + + //helper macro for setting up the irq configuration bitmaps for a standard PPE + .macro .std_irq_config irq_num=-1 irq_type=-1 irq_polarity=-1 irq_mask=-1 parms:vararg + .if (( \irq_num == -1 ) && ( \irq_type == -1 ) && ( \irq_polarity == -1 ) && ( \irq_mask == -1 )) +#.if ( .ext_irqs_defd != .ext_irqs_valid ) +#.error "###### .std_irq_config: Missing configuration for one or more interrupts ######" +#.endif + + .section .sdata + .align 3 + .global g_ext_irqs_type + .global g_ext_irqs_polarity + .global g_ext_irqs_enable + g_ext_irqs_polarity: + .quad .ext_irqs_polarity + g_ext_irqs_type: + .quad .ext_irqs_type + g_ext_irqs_enable: + .quad .ext_irqs_enable + .else + .if (( \irq_num < 0 ) || ( \irq_num > (EXTERNAL_IRQS - 1))) + .error "###### .std_irq_config: invalid irq number \irq_num ######" + .elseif ((.ext_irqs_valid & (1 << ( EXTERNAL_IRQS - 1 - \irq_num ))) == 0 ) + .error "###### .std_irq_config: Attempt to configure invalid irq number \irq_num ######" + .elseif (.ext_irqs_defd & (1 << ( EXTERNAL_IRQS - 1 - \irq_num ))) + .error "###### .std_irq_config: duplicate definition for irq \irq_num ######" + .else + .ext_irqs_defd = .ext_irqs_defd | (1 << ( EXTERNAL_IRQS - 1 - \irq_num )) + .endif + + .if (( \irq_type < 0 ) || ( \irq_type > 1 )) + .error "###### .std_irq_config: invalid/unspecified irq type \irq_type for irq \irq_num ######" + .else + .ext_irqs_type = .ext_irqs_type | ( \irq_type << ( EXTERNAL_IRQS - 1 - \irq_num )) + .endif + + .if (( \irq_polarity < 0 ) || ( \irq_polarity > 1 )) + .error "###### .std_irq_config: invalid/unspecified irq polarity ( \irq_polarity ) for irq \irq_num ######" + .else + .ext_irqs_polarity = .ext_irqs_polarity | ( \irq_polarity << ( EXTERNAL_IRQS - 1 - \irq_num )) + .endif + + .if (( \irq_mask < 0 ) || ( \irq_mask > 1 )) + .error "###### .std_irq_config: invalid/unspecified irq mask ( \irq_mask ) for irq \irq_num ######" + .else + .ext_irqs_enable = .ext_irqs_enable | ( \irq_mask << ( EXTERNAL_IRQS - 1 - \irq_num )) + .endif + + .std_irq_config \parms + .endif + .endm + + //Top level macro for generating interrupt configuration globals for a standard PPE + .macro .std_irq_cfg_bitmaps + .ext_irqs_valid = ~(APPCFG_IRQ_INVALID_MASK) + .ext_irqs_type = 0 + .ext_irqs_polarity = 0 + .ext_irqs_enable = 0 + .irq_mask = 0 + .ext_irqs_defd = 0 + .std_irq_config APPCFG_EXT_IRQS_CONFIG + .endm + +#endif /*__ASSEMBLER__*/ + +#endif /*__STD_IRQ_CONFIG_H__*/ diff --git a/src/ppe/pk/std/std_irq_init.c b/src/ppe/pk/std/std_irq_init.c new file mode 100644 index 0000000..c7a0771 --- /dev/null +++ b/src/ppe/pk/std/std_irq_init.c @@ -0,0 +1,129 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/std/std_irq_init.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file std_irq_init.c +/// \brief Standard PPE IRQ initialization code for PK +/// +/// The entry points in this file are initialization routines that could be +/// eliminated/deallocated by the application to free up storage if they are +/// no longer needed after initialization. + +#include "pk.h" + +/// Define the polarity and trigger condition for an interrupt. +/// +/// It is up to the application to take care of any side effects that may +/// occur from programming or reprogramming the interrupt controller. For +/// example, changing edge/level sensitivity or active level may set or clear +/// interrupt status in the controller. +/// +/// Note that PK allows this API to be called from any context, and changes +/// to the interrupt controller are made from a critical section. +/// +/// Return values other then PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_ARGUMENT_IRQ_SETUP One or more arguments are invalid, +/// including an invalid \a irq, or invalid \a polarity or \a trigger parameters. + +int +pk_irq_setup(PkIrqId irq, + int polarity, + int trigger) +{ + PkMachineContext ctx; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(!STD_IRQ_VALID(irq) || + !((polarity == PK_IRQ_POLARITY_ACTIVE_HIGH) || + (polarity == PK_IRQ_POLARITY_ACTIVE_LOW)) || + !((trigger == PK_IRQ_TRIGGER_LEVEL_SENSITIVE) || + (trigger == PK_IRQ_TRIGGER_EDGE_SENSITIVE)), + PK_INVALID_ARGUMENT_IRQ_SETUP); + } + + pk_critical_section_enter(&ctx); + + if (polarity == PK_IRQ_POLARITY_ACTIVE_HIGH) { + out64(STD_LCL_EIPR_OR, STD_IRQ_MASK64(irq)); + } else { + out64(STD_LCL_EIPR_CLR, STD_IRQ_MASK64(irq)); + } + + if (trigger == PK_IRQ_TRIGGER_EDGE_SENSITIVE) { + out64(STD_LCL_EITR_OR, STD_IRQ_MASK64(irq)); + } else { + out64(STD_LCL_EITR_CLR, STD_IRQ_MASK64(irq)); + } + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + +/// (Re)define the IRQ handler and priority for an interrupt. +/// Return values other then PK_OK (0) are errors; see \ref pk_errors +/// +/// Note that PK allows this API to be called from any context, and changes +/// to the interrupt controller are made from a critical section. +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_ARGUMENT_IRQ_HANDLER One or more arguments are +/// invalid, including an invalid \a irq, a null (0) \a handler, +/// or invalid \a priority. + +int +pk_irq_handler_set(PkIrqId irq, + PkIrqHandler handler, + void *arg) +{ + PkMachineContext ctx; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(!STD_IRQ_VALID(irq) || + (handler == 0), + PK_INVALID_ARGUMENT_IRQ_HANDLER); + } + + pk_critical_section_enter(&ctx); + + __ppe42_irq_handlers[irq].handler = handler; + __ppe42_irq_handlers[irq].arg = arg; + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + + diff --git a/src/ppe/pk/std/std_register_addresses.h b/src/ppe/pk/std/std_register_addresses.h new file mode 100644 index 0000000..8cf671a --- /dev/null +++ b/src/ppe/pk/std/std_register_addresses.h @@ -0,0 +1,73 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/std/std_register_addresses.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __STD_REGISTER_ADDRESSES_H__ +#define __STD_REGISTER_ADDRESSES_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file std_register_addresses.h +/// \brief Symbolic addresses for a standard PPE + +#include "pk.h" + +// Define the base address for the external interrupt controller registers +// This can be overridden in the pk_app_cfg.h file +#ifndef STD_EIC_BASE +#define STD_EIC_BASE 0xC0000000 +#endif + +// Define the base address for the PPE mode registers +// This can be overridden in the pk_app_cfg.h file +#ifndef STD_PMR_BASE +#define STD_PMR_BASE 0xC0000100 +#endif + +// Note: This list only contains registers that are needed by PK. If +// an application requires other registers, it should define them +// elsewhere (i.e., cme_register_addresses.h) +#define STD_LCL_EISR (STD_EIC_BASE + 0x0000) +#define STD_LCL_EISR_OR (STD_EIC_BASE + 0x0010) +#define STD_LCL_EISR_CLR (STD_EIC_BASE + 0x0018) +#define STD_LCL_EIMR (STD_EIC_BASE + 0x0020) +#define STD_LCL_EIMR_OR (STD_EIC_BASE + 0x0030) +#define STD_LCL_EIMR_CLR (STD_EIC_BASE + 0x0038) +#define STD_LCL_EIPR (STD_EIC_BASE + 0x0040) +#define STD_LCL_EIPR_OR (STD_EIC_BASE + 0x0050) +#define STD_LCL_EIPR_CLR (STD_EIC_BASE + 0x0058) +#define STD_LCL_EITR (STD_EIC_BASE + 0x0060) +#define STD_LCL_EITR_OR (STD_EIC_BASE + 0x0070) +#define STD_LCL_EITR_CLR (STD_EIC_BASE + 0x0078) +#define STD_LCL_EISTR (STD_EIC_BASE + 0x0080) +#define STD_LCL_EINR (STD_EIC_BASE + 0x00a0) + +#define STD_LCL_TSEL (STD_PMR_BASE + 0x0000) +#define STD_LCL_TBR (STD_PMR_BASE + 0x0040) + +#endif // __STD_REGISTER_ADDRESSES_H__ + diff --git a/src/ppe/pk/std/std_timebase.h b/src/ppe/pk/std/std_timebase.h new file mode 100644 index 0000000..10cacf9 --- /dev/null +++ b/src/ppe/pk/std/std_timebase.h @@ -0,0 +1,66 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/std/std_timebase.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __STD_TIMEBASE_H__ +#define __STD_TIMEBASE_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file std_timebase.h +/// \brief support for using the standard PPE 32 bit timebase register +/// +/// Each standard PPE has it's own timebase register that runs at a constant +/// frequency. + +#include "pk.h" + +#ifndef __ASSEMBLER__ + +#ifndef APPCFG_USE_EXT_TIMEBASE +static inline +uint32_t pk_timebase32_get(void) +{ + return (uint32_t)((in64(STD_LCL_TBR)) >> 32); +} + +#else +//assembly function is defined in ppe42_timebase.S +uint32_t pk_timebase32_get(void); + +#endif /* APPCFG_USE_EXT_TIMEBASE */ + +#else + + .macro _pk_timebase32_get rT, rA + lis \rA, STD_LCL_TBR@ha + lvd \rT, STD_LCL_TBR@l(\rA) + .endm + +#endif /* __ASSEMBLER__ */ + +#endif /* __STD_TIMEBASE_H__ */ diff --git a/src/ppe/pk/trace/Makefile b/src/ppe/pk/trace/Makefile new file mode 100644 index 0000000..45f5a44 --- /dev/null +++ b/src/ppe/pk/trace/Makefile @@ -0,0 +1,50 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/trace/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# This Makefile is designed to be invoked with the -I argument set to +# the location of the "pk.mk" for the build + +include img_defs.mk +include pktracefiles.mk + +ifeq "$(PK_TIMER_SUPPORT)" "1" +PKTRACE_OBJECTS += ${PKTRACE-TIMER-C-SOURCES:.c=.o} ${PKTRACE-TIMER-S-SOURCES:.S=.o} +endif + +ifeq "$(PK_THREAD_SUPPORT)" "1" +PKTRACE_OBJECTS += ${PKTRACE-THREAD-C-SOURCES:.c=.o} ${PKTRACE-THREAD-S-SOURCES:.S=.o} +endif + +OBJS := $(addprefix $(OBJDIR)/, $(PKTRACE_OBJECTS)) + +all: $(OBJS) + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/pk/trace/pk_trace.h b/src/ppe/pk/trace/pk_trace.h new file mode 100644 index 0000000..81d8eaf --- /dev/null +++ b/src/ppe/pk/trace/pk_trace.h @@ -0,0 +1,303 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/trace/pk_trace.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_TRACE_H__ +#define __PK_TRACE_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_trace.h +/// \brief Macros and declarations for the PK Firmware Tracing Facility. +/// + +#include <stdint.h> + +#define PK_TRACE_VERSION 2 + +#ifndef PK_TRACE_SZ +#define PK_TRACE_SZ 256 +#endif + +//Fail compilation if size is not a power of 2 +#if ((PK_TRACE_SZ - 1) & PK_TRACE_SZ) +#error "PK_TRACE_SZ is not a power of two!!!" +#endif + +//Fail compilation if size is smaller than 64 bytes +#if (PK_TRACE_SZ < 64) +#error "PK_TRACE_SZ must be at least 64 bytes!!!" +#endif + +//Mask for calculating offsets into the trace circular buffer +#define PK_TRACE_CB_MASK (PK_TRACE_SZ - 1) + +#define STRINGIFY_HELPER(x) #x +#define STRINGIFY(x) STRINGIFY_HELPER(x) + +#define PPE_IMG_STRING STRINGIFY(IMAGE_NAME) + +#ifdef PK_TRACE_HASH_PREFIX +#if (PK_TRACE_HASH_PREFIX > 0xffff) +#error PK_TRACE_HASH_PREFIX must be defined as a 16 bit constant value +#endif +#endif //PK_TRACE_HASH_PREFIX + +//This provides a 128ns tick (assuming a 32ns clock period) +//and 4 different format values +#define PK_TRACE_TS_BITS 30 + +#define PK_TRACE_FORMAT_BITS (32 - PK_TRACE_TS_BITS) + +#define PK_TRACE_TS_MASK (0xfffffffful << PK_TRACE_FORMAT_BITS) +#define PK_TRACE_FORMAT_MASK (~PK_TRACE_TS_MASK) + +#define PK_GET_TRACE_FORMAT(w32) (PK_TRACE_FORMAT_MASK & w32) +#define PK_GET_TRACE_TIME(w32) (PK_TRACE_TS_MASK & w32) + +//Set the trace timer period to be the maximum +//32 bit time minus 2 seconds (assuming a 32ns tick) +//This allows for up to 1 second of interrupt latency + +//1 second for PK_TRACE_MTBT while only requiring a trace +//every 135 seconds in order to maintain the 64bit timebase. +#define PK_TRACE_TIMER_PERIOD (0xfffffffful - 62500000) + +//The Maximum Time Between Traces. In order to reduce the time that interrupts +//are disabled for tracing, reading of the time stamp is not done atomically +//with alocating an entry in the circular buffer. This means that the +//timestamps might not appear in order in the trace buffer. This is a +//problem because our calculation of the 64 bit timebase uses the unsigned +//difference of the current 32bit timestamp and the previous one and if they +//are out of order it will result in a very large difference. To solve this +//problem, any time that the parser code sees a very large difference (larger +//than PK_TRACE_MTBT) it will treat it as a negative number. +#define PK_TRACE_MTBT (0xfffffffful - 31250000) + +#define PK_TRACE_MAX_PARMS 4 + +//This is the maximum number of bytes allowed to be traced in a binary trace +//entry. +//The trace version needs to change if this changes. +#define PK_TRACE_MAX_BINARY 256 + +//clip the largest binary trace according to the trace buffer size. +//(The trace version does not need to change if this changes as long +// as it remains less than PK_TRACE_MAX_BINARY) +#if (PK_TRACE_SZ <= 256) +#define PK_TRACE_CLIPPED_BINARY_SZ PK_TRACE_SZ / 2 +#else +#define PK_TRACE_CLIPPED_BINARY_SZ PK_TRACE_MAX_BINARY +#endif + +//Trace formats that are supported +typedef enum +{ + PK_TRACE_FORMAT_EMPTY, + PK_TRACE_FORMAT_TINY, + PK_TRACE_FORMAT_BIG, + PK_TRACE_FORMAT_BINARY, +}PkTraceFormat; //pk_trace_format_t; + +//This combines the timestamp and the format bits into a +//single 32 bit word. +typedef union +{ + struct + { + uint32_t timestamp : PK_TRACE_TS_BITS; + uint32_t format : PK_TRACE_FORMAT_BITS; + }; + uint32_t word32; +}PkTraceTime; //pk_trace_time_t; + +//PK trace uses a 16 bit string format hash value +typedef uint16_t PkTraceHash; //pk_trace_hash_t; + +//The constant 16 bit hash value is combined with a +//16 bit parameter value when doing a tiny trace +typedef union +{ + struct + { + PkTraceHash string_id; + uint16_t parm; + }; + uint32_t word32; +}PkTraceTinyParms; //pk_trace_tiny_parms_t; + +//A tiny trace fits within a single 8 byte word. This includes +//the timestamp, format bits, hash id, and a 16 bit parameter. +typedef union +{ + struct + { + PkTraceTinyParms parms; + PkTraceTime time_format; + }; + uint64_t word64; +}PkTraceTiny; //pk_trace_tiny_t; + +//Larger traces that require a 32 bit parameter or more than one +//parameter use the big trace format. The number of parms and +//the 'complete' flag are combined with the hash id. 'complete' +//is set to 0 initially and set to one only after all of the trace +//data has been written. +typedef union +{ + struct + { + PkTraceHash string_id; + uint8_t complete; + uint8_t num_parms; + }; + uint32_t word32; +}PkTraceBigParms; //pk_trace_big_parms_t; + +typedef union +{ + struct + { + PkTraceBigParms parms; + PkTraceTime time_format; + }; + uint64_t word64; +}PkTraceBig; //pk_trace_big_t; + +//Binary traces are handled in a similar fashion to big traces, except +//that instead of having a number of parameters, we have number of bytes. +typedef union +{ + struct + { + PkTraceHash string_id; + uint8_t complete; + uint8_t num_bytes; + }; + uint32_t word32; +}PkTraceBinaryParms; //pk_trace_binary_parms_t; + +typedef union +{ + struct + { + PkTraceBinaryParms parms; + PkTraceTime time_format; + }; + uint64_t word64; +}PkTraceBinary; //pk_trace_binary_t; + +//This is a generic structure that can be used to retrieve data +//for tiny, big, and binary formatted entries. +typedef union +{ + struct + { + PkTraceHash string_id; + union + { + uint16_t parm16; + struct + { + uint8_t complete; + uint8_t bytes_or_parms_count; + }; + }; + PkTraceTime time_format; + }; + uint64_t word64; +}PkTraceGeneric; //pk_trace_generic_t; + +//This is a format that might be used in the future for tracing +//a 64 bit timestamp so that we don't fill up the buffer with periodic +//timer traces. It is not currently used. +#if 0 +typedef union +{ + struct + { + uint32_t upper32; + PkTraceTime time_format; + }; + uint64_t word64; +}PkTraceTime64; //pk_trace_time64_t; +#endif + +//It would probably be more accurate to call this a footer since it +//actually resides at the highest address of each trace entry. These eight +//bytes contain information that allow us to walk the trace buffer from the +//most recent entry to the oldest entry. +typedef union +{ + PkTraceGeneric generic; + PkTraceBinary binary; + PkTraceBig big; + PkTraceTiny small; +}PkTraceEntryFooter; //pk_trace_entry_header_t; + + +//This is the data that is updated (in the buffer header) every time we add +//a new entry to the buffer. +typedef union +{ + struct + { + uint32_t tbu32; + uint32_t offset; + }; + uint64_t word64; +}PkTraceState; //pk_trace_state_t; + +#define PK_TRACE_IMG_STR_SZ 16 + +//Header data for the trace buffer that is used for parsing the data. +//Note: pk_trace_state_t contains a uint64_t which is required to be +//placed on an 8-byte boundary according to the EABI Spec. This also +//causes cb to start on an 8-byte boundary. +typedef struct +{ + //these values are needed by the parser + uint16_t version; + uint16_t rsvd; + char image_str[PK_TRACE_IMG_STR_SZ]; + uint16_t instance_id; + uint16_t partial_trace_hash; + uint16_t hash_prefix; + uint16_t size; + uint32_t max_time_change; + uint32_t hz; + uint32_t pad; + uint64_t time_adj64; + + //updated with each new trace entry + PkTraceState state; + + //circular trace buffer + uint8_t cb[PK_TRACE_SZ]; +}PkTraceBuffer; //pk_trace_buffer_t; + +extern PkTraceBuffer g_pk_trace_buf; + +#endif /* __PK_TRACE_H__ */ diff --git a/src/ppe/pk/trace/pk_trace_big.c b/src/ppe/pk/trace/pk_trace_big.c new file mode 100644 index 0000000..46c0eed --- /dev/null +++ b/src/ppe/pk/trace/pk_trace_big.c @@ -0,0 +1,116 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/trace/pk_trace_big.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_trace_big.c +/// \brief PK Trace function that supports up to four 32-bit parameters +/// +/// The pk_trace_big function is only called (via some macro magic) if the +/// caller passes in a single parameter (not including the format string) +/// that is larger than 16 bits to the PK_TRACE(...) macro. +/// + +#include "pk.h" +#include "pk_trace.h" + +#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) +void pk_trace_big(uint32_t i_hash_and_count, + uint64_t i_parm1, uint64_t i_parm2) +{ + PkTraceBig footer; + PkTraceBig* footer_ptr; + PkTraceState state; + uint64_t* ptr64; + uint64_t tb64; + PkMachineContext ctx; + uint32_t parm_size; + uint32_t cur_offset; + uint32_t footer_offset; + + //fill in the footer data + tb64 = pk_timebase_get(); + footer.parms.word32 = i_hash_and_count; //this has the parm count and hash + state.tbu32 = tb64 >> 32; + footer.time_format.word32 = tb64 & 0x00000000ffffffffull; + footer.time_format.format = PK_TRACE_FORMAT_BIG; + + //round up to 8 byte boundary + if(footer.parms.num_parms <= 2) + { + parm_size = 8; + } + else + { + parm_size = 16; + } + + //*****The following operations must be done atomically***** + pk_critical_section_enter(&ctx); + + //load in the offset in the cb for the entry we are adding + cur_offset = g_pk_trace_buf.state.offset; + + //Find the offset for the footer (at the end of the entry) + footer_offset = cur_offset + parm_size; + + //calculate the address of the footer + ptr64 = (uint64_t*)&g_pk_trace_buf.cb[footer_offset & PK_TRACE_CB_MASK]; + + //calculate the offset for the next entry in the cb + state.offset = footer_offset + sizeof(PkTraceBig); + + //update the cb state (tbu and offset) + g_pk_trace_buf.state.word64 = state.word64; + + //write the data to the circular buffer including the + //timesamp, string hash, and 16bit parameter + *ptr64 = footer.word64; + + //*******************exit the critical section*************** + pk_critical_section_exit(&ctx); + + + //write parm values to the circular buffer + footer_ptr = (PkTraceBig*)ptr64; + ptr64 = (uint64_t*)&g_pk_trace_buf.cb[cur_offset & PK_TRACE_CB_MASK]; + *ptr64 = i_parm1; + if(parm_size > 8) + { + ptr64 = (uint64_t*)&g_pk_trace_buf.cb[(cur_offset + 8) & PK_TRACE_CB_MASK]; + *ptr64 = i_parm2; + } + + //Mark the trace entry update as being completed + footer_ptr->parms.complete = 1; + +} + +#endif + + diff --git a/src/ppe/pk/trace/pk_trace_binary.c b/src/ppe/pk/trace/pk_trace_binary.c new file mode 100644 index 0000000..a510d9d --- /dev/null +++ b/src/ppe/pk/trace/pk_trace_binary.c @@ -0,0 +1,115 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/trace/pk_trace_binary.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_trace_binary.c +/// \brief PK Trace function for dumping memory contents +/// +/// The pk_trace_binary function is called by the PK_TRACE_BINARY() macro. +/// + + +#include "pk.h" +#include "pk_trace.h" + +#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) +void pk_trace_binary(uint32_t i_hash_and_size, void* bufp) +{ + PkTraceBinary footer; + PkTraceBinary* footer_ptr; + PkTraceState state; + uint64_t* ptr64; + uint64_t tb64; + PkMachineContext ctx; + uint32_t data_size; + uint32_t cb_offset; + uint32_t footer_offset; + uint8_t* dest; + uint8_t* src; + uint32_t index; + + //fill in the footer data + tb64 = pk_timebase_get(); + footer.parms.word32 = i_hash_and_size; //this has the size and hash + state.tbu32 = tb64 >> 32; + footer.time_format.word32 = tb64 & 0x00000000ffffffffull; + footer.time_format.format = PK_TRACE_FORMAT_BINARY; + + //round up to 8 byte boundary + data_size = (footer.parms.num_bytes + 7) & ~0x00000007ul; + + //limit data size + if(data_size > PK_TRACE_CLIPPED_BINARY_SZ) + { + data_size = PK_TRACE_CLIPPED_BINARY_SZ; + } + + //*****The following operations must be done atomically***** + pk_critical_section_enter(&ctx); + + //load in the offset in the cb for the entry we are adding + cb_offset = g_pk_trace_buf.state.offset; + + //Find the offset for the footer (at the end of the entry) + footer_offset = cb_offset + data_size; + + //calculate the address of the footer + ptr64 = (uint64_t*)&g_pk_trace_buf.cb[footer_offset & PK_TRACE_CB_MASK]; + + //calculate the offset for the next entry in the cb + state.offset = footer_offset + sizeof(PkTraceBinary); + + //update the cb state (tbu and offset) + g_pk_trace_buf.state.word64 = state.word64; + + //write the footer data to the circular buffer including the + //timesamp, string hash and data size + *ptr64 = footer.word64; + + //*******************exit the critical section*************** + pk_critical_section_exit(&ctx); + + //write data to the circular buffer + for(src = bufp, index = 0; + index < data_size; + index++) + { + dest = &g_pk_trace_buf.cb[(cb_offset + index) & PK_TRACE_CB_MASK]; + *dest = *(src++); + } + + //Mark the trace entry update as being completed + footer_ptr = (PkTraceBinary*)ptr64; + footer_ptr->parms.complete = 1; + +} + +#endif + + diff --git a/src/ppe/pk/trace/pk_trace_core.c b/src/ppe/pk/trace/pk_trace_core.c new file mode 100644 index 0000000..17aaca1 --- /dev/null +++ b/src/ppe/pk/trace/pk_trace_core.c @@ -0,0 +1,140 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/trace/pk_trace_core.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_trace_core.c +/// \brief PK Trace core data and code. +/// +/// This file includes the minimal code/data required to do minimal tracing. +/// This includes the periodic timer initialization and the pk_trace_tiny +/// function. The pk_trace_tiny function is called by the PK_TRACE() macro +/// when there is one or less parameters (not including the format string) +/// and the parameter size is 16 bits or smaller. +/// + +#include "pk.h" +#include "pk_trace.h" + +void pk_trace_timer_callback(void* arg); + +#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) + +//Static initialization of the trace timer +PkTimer g_pk_trace_timer = { + .deque = PK_DEQUE_ELEMENT_INIT(), + .timeout = 0, + .callback = pk_trace_timer_callback, + .arg = 0, +}; + +//Static initialization of the pk trace buffer +PkTraceBuffer g_pk_trace_buf = +{ + .version = PK_TRACE_VERSION, + .image_str = PPE_IMG_STRING, + .hash_prefix = PK_TRACE_HASH_PREFIX, + .partial_trace_hash = trace_ppe_hash("PARTIAL TRACE ENTRY. HASH_ID = %d", PK_TRACE_HASH_PREFIX), + .size = PK_TRACE_SZ, + .max_time_change = PK_TRACE_MTBT, + .hz = 500000000, //default value. Actual value is set in pk_init.c + .time_adj64 = 0, + .state.word64 = 0, + .cb = {0} +}; + +//Needed for buffer extraction in simics for now +PkTraceBuffer* g_pk_trace_buf_ptr = &g_pk_trace_buf; + +// Creates an 8 byte entry in the trace buffer that includes a timestamp, +// a format string hash value and a 16 bit parameter. +// +// i_parm has the hash value combined with the 16 bit parameter +void pk_trace_tiny(uint32_t i_parm) +{ + PkTraceTiny footer; + PkTraceState state; + uint64_t* ptr64; + uint64_t tb64; + PkMachineContext ctx; + + //fill in the footer data + footer.parms.word32 = i_parm; + tb64 = pk_timebase_get(); + state.tbu32 = tb64 >> 32; + footer.time_format.word32 = tb64 & 0x00000000ffffffffull; + + footer.time_format.format = PK_TRACE_FORMAT_TINY; + + //The following operations must be done atomically + pk_critical_section_enter(&ctx); + + //load the current byte count and calculate the address for this + //entry in the cb + ptr64 = (uint64_t*)&g_pk_trace_buf.cb[g_pk_trace_buf.state.offset & PK_TRACE_CB_MASK]; + + //calculate the offset for the next entry in the cb + state.offset = g_pk_trace_buf.state.offset + sizeof(PkTraceTiny); + + //update the cb state (tbu and offset) + g_pk_trace_buf.state.word64 = state.word64; + + //write the data to the circular buffer including the + //timesamp, string hash, and 16bit parameter + *ptr64 = footer.word64; + + //exit the critical section + pk_critical_section_exit(&ctx); +} + + +// This function is called periodically in order to ensure that the max ticks +// between trace entries is no more than what will fit inside a 32bit value. +void pk_trace_timer_callback(void* arg) +{ + + // guarantee at least one trace before the lower 32bit timebase flips + PK_TRACE("PERIODIC TIMESTAMPING TRACE"); + + // restart the timer + pk_timer_schedule(&g_pk_trace_timer, + PK_TRACE_TIMER_PERIOD); +} + +// Use this function to synchronize the timebase between multiple PPEs. +// PPE A can send PPE B it's current timebase and then PPE B can set that +// as the current timebase for tracing purposes. It can also be used +// to set the current time to 0. This function changes the timebase for +// all entries that are currently in the trace buffer. Setting the current +// timebase to 0 will cause previous traces to have very large timestamps. +void pk_trace_set_timebase(PkTimebase timebase) +{ + g_pk_trace_buf.time_adj64 = timebase - pk_timebase_get(); +} + +#endif diff --git a/src/ppe/pk/trace/pktracefiles.mk b/src/ppe/pk/trace/pktracefiles.mk new file mode 100644 index 0000000..5ef8823 --- /dev/null +++ b/src/ppe/pk/trace/pktracefiles.mk @@ -0,0 +1,63 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/pk/trace/pktracefiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file pkppe42files.mk +# +# @brief mk for including ppe42 object files +# +# @page ChangeLogs Change Logs +# @section pkppe42files.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# Include Files +########################################################################## + + + +########################################################################## +# Object Files +########################################################################## +PKTRACE-C-SOURCES = pk_trace_core.c pk_trace_big.c pk_trace_binary.c + +PKTRACE-S-SOURCES = + +PKTRACE-TIMER-C-SOURCES = +PKTRACE-TIMER-S-SOURCES = + +PKTRACE-THREAD-C-SOURCES += +PKTRACE-THREAD-S-SOURCES += + + +PKTRACE_OBJECTS += $(PKTRACE-C-SOURCES:.c=.o) $(PKTRACE-S-SOURCES:.S=.o) + + + diff --git a/src/ppe/sbe/.empty b/src/ppe/sbe/.empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ppe/sbe/.empty diff --git a/src/ppe/sbe/image/Makefile b/src/ppe/sbe/image/Makefile new file mode 100644 index 0000000..a784342 --- /dev/null +++ b/src/ppe/sbe/image/Makefile @@ -0,0 +1,222 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/sbe/image/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +#remove this once we have a real compiler +export P2P_ENABLE = 1 + +#remove this once we have a real compiler +export SBEFW_ENABLE = 1 + +#Pull in the definitions that affect all makefiles for this image +include img_defs.mk + +#Pull in object file names for the top directory +include topfiles.mk + +ifdef P2P_ENABLE +include $(P2P_SRCDIR)/p2pfiles.mk +endif + +#Pull in PPE complier libraries . +# Sets up the following variables: +# $(GCCLIBS) -> Libary objects to be linked +# $(LIB_DIRS) -> Include directories +include ../../include/ppe_compiler.mk + + +PK_MAKE_DIR := $(PK_SRCDIR)/$(PPE_TYPE) +LIB_DIRS += -L$(OBJDIR)/pk +PKLIB := $(OBJDIR)/pk/libpk.a +LLIBS += -lpk + +SBEFW_MAKE_DIR := ../sbefw +LIB_DIRS += -L$(OBJDIR)/sbefw +SBEFWLIB := $(OBJDIR)/sbefw/libsbefw.a +LLIBS += -lsbefw + +SAMPLE_MAKE_DIR := ../sample +LIB_DIRS += -L$(OBJDIR)/sample +SAMPLELIB := $(OBJDIR)/sample/libsample.a +#LLIBS += -lsample + +# FAPI2 library +FAPI2_MAKE_DIR := $(PLAT_FAPI2_DIR) +LIB_DIRS += -L$(OBJDIR)/fapi2 +FAPI2LIB := $(OBJDIR)/fapi2/libfapi2.a +LLIBS += -lfapi2 + +ifdef P2P_ENABLE +LIB_DIRS += -L$(OBJDIR)/p2p +P2PLIB := $(OBJDIR)/p2p/libp2p.a +LINK_OBJS += $(P2PLIB) +LLIBS += -lp2p +endif + +# HWP LIB library +HWPLIB_MAKE_DIR := $(HWPLIB_SRCDIR) +LIB_DIRS += -L$(OBJDIR)/lib +HWPLIB := $(OBJDIR)/libcommon.a +LLIBS += -lcommon + +# Common Cache HWP Exit library +CACHE_MAKE_DIR := $(CACHE_SRCDIR) +LIB_DIRS += -L$(OBJDIR)/cache +CACHELIB := $(OBJDIR)/cache/libcache.a +LLIBS += -lcache + + +# Common Core libraries +CORE_MAKE_DIR := $(CORE_SRCDIR) +LIB_DIRS += -L$(OBJDIR)/core +CORELIB := $(OBJDIR)/core/libcore.a +LLIBS += -lcore + +# Common Perv libraries +PERV_MAKE_DIR := $(PERV_SRCDIR) +LIB_DIRS += -L$(OBJDIR)/perv +PERVLIB := $(OBJDIR)/perv/libperv.a +LLIBS += -lperv + +LINK_OBJS = $(OBJS) $(PKLIB) $(SBEFWLIB) $(FAPI2LIB) $(CACHELIB) $(CORELIB) $(HWPLIB) $(P2PLIB) $(PERVLIB) + +# Define the objects +OBJS := $(addprefix $(OBJDIR)/, $(TOP_OBJECTS)) +LINK_OBJS += $(OBJS) $(GCCLIBS) +#LINK_OBJS += $(OBJS) $(PKLIB) $(CPPLIB) $(PPELIB) +LINK_SCRIPT = $(addprefix $(OBJDIR)/, linkscript) + + + +#default target is to make a binary application image +#This removes all unecessary headers from the ELF executable +$(OBJDIR)/$(IMAGE_NAME).bin $(OBJDIR)/$(IMAGE_NAME).dis: $(OBJDIR)/$(IMAGE_NAME).out + $(OBJCOPY) -O binary $< $(OBJDIR)/$(IMAGE_NAME).bin --pad-to 0x`/usr/bin/nm $(OBJDIR)/$(IMAGE_NAME).out | grep "A _sbe_base_end" | cut -d " " -f 1` + $(OBJDUMP) -S $< > $(OBJDIR)/$(IMAGE_NAME).dis + +#create a linked ELF executable +$(OBJDIR)/$(IMAGE_NAME).out: $(LINK_OBJS) $(LINK_SCRIPT) + $(LD) -e __system_reset -T$(LINK_SCRIPT) -Map $(OBJDIR)/$(IMAGE_NAME).map -Bstatic -o $(OBJDIR)/$(IMAGE_NAME).out $(LIB_DIRS) $(OBJS) --start-group $(LLIBS) --end-group +# $(LD) -e __system_reset -T$(LINK_SCRIPT) -Map $(OBJDIR)/$(IMAGE_NAME).map -Bstatic -o $(OBJDIR)/$(IMAGE_NAME).out $(LIB_DIRS) $(OBJS) -lpk -lp2p #-lcommon +# $(LD) -e __system_reset -T$(LINK_SCRIPT) -Map $(OBJDIR)/$(IMAGE_NAME).map -Bstatic -o $(OBJDIR)/$(IMAGE_NAME).out $(LIB_DIRS) $(OBJS) $(LLIBS) + + +#pass the link command file through the C preprocessor to evaluate macros and remove comments +$(LINK_SCRIPT): link.cmd + $(CPP) -E -x c++ -P $(DEFS) link.cmd -o $(LINK_SCRIPT) + +#Create an obj directory if needed +$(LINK_OBJS) $(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + $(BASE_FAPI2_DIR)/tools/ppeParseProcSbeFixed.pl . $(TOOLS_ATTR_DIR)/p9_ppe_attributes1.xml $(ATTRFILES) + $(BASE_FAPI2_DIR)/tools/ppeParseAttributeInfo.pl $(PPE_FAPI2_DIR)/include $(TOOLS_ATTR_DIR)/p9_ppe_attributes1.xml $(ATTRFILES) + $(BASE_FAPI2_DIR)/tools/ppeCreateAttrGetSetMacros.pl -path $(BASE_FAPI2_DIR)/tools -inc $(PPE_FAPI2_DIR)/include -src $(PPE_FAPI2_DIR)/src + $(BASE_FAPI2_DIR)/tools/ppeCreateIfAttrService.pl $(PPE_FAPI2_DIR)/include $(TOOLS_ATTR_DIR)/p9_ppe_attributes1.xml $(ATTRFILES) + mkdir -p $(OBJDIR) + +.PHONY: clean topfixedheaders $(PKLIB) $(P2PLIB) $(SBEFWLIB) $(PPELIB) $(FAPI2LIB) $(CACHELIB) $(CORELIB) $(PERVLIB) $(HWPLIB) + +ATTRFILES += $(TOOLS_ATTR_DIR)/perv_attributes.xml +ATTRFILES += $(TOOLS_ATTR_DIR)/proc_attributes.xml +ATTRFILES += $(TOOLS_ATTR_DIR)/ex_attributes.xml +ATTRFILES += $(TOOLS_ATTR_DIR)/eq_attributes.xml +ATTRFILES += $(TOOLS_ATTR_DIR)/core_attributes.xml + +topfixedheaders: + $(BASE_FAPI2_DIR)/tools/ppeParseProcSbeFixed.pl . $(TOOLS_ATTR_DIR)/p9_ppe_attributes1.xml $(ATTRFILES) + +attrids: + $(BASE_FAPI2_DIR)/tools/ppeParseAttributeInfo.pl $(PPE_FAPI2_DIR)/include $(TOOLS_ATTR_DIR)/p9_ppe_attributes1.xml $(ATTRFILES) + +platattr: + $(BASE_FAPI2_DIR)/tools/ppeCreateAttrGetSetMacros.pl --path $(BASE_FAPI2_DIR)/tools --inc $(PPE_FAPI2_DIR)/include --src $(PPE_FAPI2_DIR)/src + +attrserv: + $(BASE_FAPI2_DIR)/tools/ppeCreateIfAttrService.pl $(PPE_FAPI2_DIR)/include $(TOOLS_ATTR_DIR)/p9_ppe_attributes1.xml $(ATTRFILES) + + +#Build macro-specific kernel code +$(PKLIB): + $(MAKE) -I $(IMAGE_SRCDIR) -C $(PK_MAKE_DIR) + +#Build macro-specific kernel code +$(SBEFWLIB): + $(MAKE) -I $(IMAGE_SRCDIR) -C $(SBEFW_MAKE_DIR) + + +#Build the code that is common for all processors (PPEs and 405) +$(PPELIB): + @echo "Processing ppelibmakefile" + $(MAKE) -I $(IMAGE_SRCDIR) -C $(LIB_MAKE_DIR) + +#Build the cache exit code shared with the SBE +$(CACHELIB): + @echo "Processing cache makefile" + $(MAKE) -I $(IMAGE_SRCDIR) -C $(CACHE_MAKE_DIR) + +#Build the core exit code shared with the SBE +$(CORELIB): + @echo "Processing core makefile" + $(MAKE) -I $(IMAGE_SRCDIR) -C $(CORE_MAKE_DIR) + +#Build the perv code +$(PERVLIB): + @echo "Processing perv makefile" + $(MAKE) -I $(IMAGE_SRCDIR) -C $(PERV_MAKE_DIR) + +#Build the comming HWP lib procedures +$(HWPLIB): + @echo "Processing HWP lib makefile" + $(MAKE) -I $(IMAGE_SRCDIR) -C $(HWPLIB_MAKE_DIR) + +#Build the FAPI2 library +$(FAPI2LIB): + @echo "Processing fapi2 makefile" + $(MAKE) -I $(IMAGE_SRCDIR) -C $(FAPI2_MAKE_DIR)/src + +ifdef P2P_ENABLE +$(P2PLIB): + $(MAKE) -I $(IMAGE_SRCDIR) -C $(P2P_SRCDIR) +endif + +# collect all of the trace hash files for this image into a single trexStringFile +.PHONY : tracehash +tracehash: + mkdir -p $(OBJDIR) + $(THASH) -c -d $(OBJDIR) -s $(OBJDIR)/trexStringFile + +#clean the kernel directory first, then the application level clean +clean: + rm -fr $(OBJDIR) + rm $(TOP-FIXED-HEADERS) + rm *.dump + + +dump: + objdump -s $(OBJDIR)/$(IMAGE_NAME).out > $(IMAGE_NAME).dump + +#Add dependencies to header files +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/sbe/image/base_main.C b/src/ppe/sbe/image/base_main.C new file mode 100644 index 0000000..92cf13b --- /dev/null +++ b/src/ppe/sbe/image/base_main.C @@ -0,0 +1,91 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/image/base_main.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file base_main.c +/// \brief base program that creates and starts a thread +/// +/// This file is a placeholder code in order to compile. I will be replaced in future by the code placed into the .text section. + +extern "C" { +#include "pk.h" +#include "pk_trace.h" +#include "base_ppe_demo.h" +#include "sbe_xip_image.h" +} +#define KERNEL_STACK_SIZE 256 +#define MAIN_THREAD_STACK_SIZE 256 + +uint8_t G_kernel_stack[KERNEL_STACK_SIZE]; +uint8_t G_main_thread_stack[MAIN_THREAD_STACK_SIZE]; +PkThread G_main_thread; + +// A simple thread that just increments a local variable and sleeps +void main_thread(void* arg) +{ + + while(1) + { + + pk_sleep(PK_SECONDS(1)); + + } +} + + +// The main function is called by the boot code (after initializing some +// registers) +int main(int argc, char **argv) +{ + // initializes kernel data (stack, threads, timebase, timers, etc.) + pk_initialize((PkAddress)G_kernel_stack, + KERNEL_STACK_SIZE, + 0, + 500000000); + + + //Initialize the thread control block for G_main_thread + pk_thread_create(&G_main_thread, + (PkThreadRoutine)main_thread, + (void*)NULL, + (PkAddress)G_main_thread_stack, + (size_t)MAIN_THREAD_STACK_SIZE, + (PkThreadPriority)1); + + + + //Make G_main_thread runnable + pk_thread_resume(&G_main_thread); + + // Start running the highest priority thread. + // This function never returns + pk_start_threads(); + + return 0; +} diff --git a/src/ppe/sbe/image/base_ppe_demo.c b/src/ppe/sbe/image/base_ppe_demo.c new file mode 100644 index 0000000..0e8ea55 --- /dev/null +++ b/src/ppe/sbe/image/base_ppe_demo.c @@ -0,0 +1,44 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/image/base_ppe_demo.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file base_ppe_demo.c +/// \brief example code to include into fixed section +/// +/// demo function to include into fixed section. Can be replaced as soon as +/// real functions are available + +#include "base_ppe_demo.h" +#include "pk.h" +#include "pk_trace.h" + +void base_ppe_demo_func(const char* str) +{ + PK_TRACE("TESTFUNCTION"); +} diff --git a/src/ppe/sbe/image/base_ppe_demo.h b/src/ppe/sbe/image/base_ppe_demo.h new file mode 100644 index 0000000..5447b0c --- /dev/null +++ b/src/ppe/sbe/image/base_ppe_demo.h @@ -0,0 +1,43 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/image/base_ppe_demo.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file base_ppe_demo.h +/// \brief routine to be placed into the fixed section. +/// +/// this routing is a demonstration for functions to be placed into the fixed +/// fixed section +#ifndef __BASE_PPE_DEMO_H__ +#define __BASE_PPE_DEMO_H__ + +/// this is a demo function whose pointer is placed into the fixed section +/// @param str demo string +void base_ppe_demo_func(const char*); + +#endif // __BASE_PPE_DEMO_H__ diff --git a/src/ppe/sbe/image/base_ppe_header.S b/src/ppe/sbe/image/base_ppe_header.S new file mode 100644 index 0000000..b694bbe --- /dev/null +++ b/src/ppe/sbe/image/base_ppe_header.S @@ -0,0 +1,220 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/image/base_ppe_header.S $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file base_ppe_header.S +/// \brief code to create header, toc, strings, fixed and fixed_toc sections +/// +/// function SbeXipHeader creates header section, function .proc_sbe_fixed +/// creates fixed, fixed_toc sections +#include "sbe_xip_image.h" +#include "proc_sbe_fixed.H" + + +#define PORE_SPACE_UNDEFINED 0xffff +#define PORE_SPACE_OCI 0x8000 +#define PORE_SPACE_PNOR 0x800b +#define PORE_SPACE_OTPROM 0x0001 +#define PORE_SPACE_SEEPROM 0x800c +#define PORE_SPACE_PIBMEM 0x0008 + + + + .macro ..checku, x:req, bits:req, err="Unsigned value too large" + + .if (((\bits) <= 0) || ((\bits) > 63)) + .error "The number of bits must be in the range 0 < bits < 64" + .endif + + .iflt (\x) + .error "An unsigned value is required here" + .endif + + .ifgt ((\x) - (0xffffffffffffffff >> (64 - (\bits)))) + .error "\err" + .endif + + .endm + + .macro ..check_u16, u16 + ..checku (\u16), 16, "Unsigned immediate is larger than 16 bits" + .endm + + + .macro ..set_default_space, s + ..check_u16 (\s) + .set _PGAS_DEFAULT_SPACE, (\s) + .endm + + .macro ..check_default_space + .if (_PGAS_DEFAULT_SPACE == PORE_SPACE_UNDEFINED) + .error "The PGAS default address space has not been defined" + .endif + .endm + + + .macro .quada, offset:req + ..check_default_space + .long _PGAS_DEFAULT_SPACE + .long (\offset) + .endm + + +// .macro SbeXipHeader, magic, link_address, entry_point, image_size + + .macro SbeXipSection, s:req, alignment=1, empty=0 +__\s\()_section: + .if \empty + .long 0 + .long 0 + .else + .long _\s\()_offset + .long _\s\()_size + .endif + .byte (\alignment) + .byte 0, 0, 0 + .endm + + + .macro SbeXipHeader, magic, link_address, entry_point, image_size + + .section .header, "a", @progbits + + + ////////////////////////////////////////////////////////////////////// + // Identification - 8-byte aligned; 8 Entries; TOC-Indexed + ////////////////////////////////////////////////////////////////////// + +__magic: + .quad (\magic) +__entry_offset: + .quad ((\entry_point) - (\link_address)) +__link_address: + .quada (\link_address) +__header_64_reserved: + .quad 0, 0, 0, 0, 0 + + .xip_toc magic, SBE_XIP_UINT64, __magic + .xip_toc entry_offset, SBE_XIP_UINT64, __entry_offset + .xip_toc link_address, SBE_XIP_UINT64, __link_address + + + ////////////////////////////////////////////////////////////////////// + // Section Table - 8-byte aligned; 16 entries; Not TOC-Indexed + ////////////////////////////////////////////////////////////////////// + + SbeXipSection header + SbeXipSection fixed, 8 + SbeXipSection fixed_toc, 8 + SbeXipSection ipl_text, 4 + SbeXipSection ipl_data, 8 + SbeXipSection text, 4 + SbeXipSection data, 8 + SbeXipSection toc, 4 + SbeXipSection strings + SbeXipSection halt, 4, empty=1 + SbeXipSection pibmem0, 8, empty=1 + SbeXipSection dcrings, 8, empty=1 + SbeXipSection rings, 8, empty=1 + SbeXipSection slw, 128, empty=1 + SbeXipSection fit, empty=1 + SbeXipSection ffdc, 8, empty=1 + + + ////////////////////////////////////////////////////////////////////// + // Other Information - 4-byte aligned; 8 entries; TOC-Indexed + ////////////////////////////////////////////////////////////////////// + +__image_size: + .long (\image_size) +__build_date: + .long 0 +__build_time: + .long 0 +__header_32_reserved: + .long 0, 0, 0, 0, 0 + + .xip_toc image_size, SBE_XIP_UINT32, __image_size + .xip_toc build_date, SBE_XIP_UINT32, __build_date + .xip_toc build_time, SBE_XIP_UINT32, __build_time + + + ////////////////////////////////////////////////////////////////////// + // Other Information - 1-byte aligned; 8 entries; TOC-Indexed + ////////////////////////////////////////////////////////////////////// + +__header_version: + .byte SBE_XIP_HEADER_VERSION +__toc_normalized: + .byte 0 +__toc_sorted: + .byte 0 +__header_8_reserved: + .byte 0, 0, 0, 0, 0 + + .xip_toc header_version, SBE_XIP_UINT8, __header_version + .xip_toc toc_normalized, SBE_XIP_UINT8, __toc_normalized + .xip_toc toc_sorted, SBE_XIP_UINT8, __toc_sorted + + + ////////////////////////////////////////////////////////////////////// + // Strings; 64 characters allocated; TOC-Indexed + ////////////////////////////////////////////////////////////////////// + +__build_user: + .asciz "unknown " # 16 Characters allocated +__build_host: + .asciz "unknown " # 24 characters allocated +__header_string_reserved: + .space 24, 0 + + .xip_toc build_user, SBE_XIP_STRING, __build_user + .xip_toc build_host, SBE_XIP_STRING, __build_host + + + .endm + + + .section .fixed, "a", @progbits + .section .fixed_toc, "a", @progbits + .section .ipl_data, "a", @progbits + .section .ipl_text, "a", @progbits + + .section .toc, "a", @progbits + .section .strings, "aS", @progbits + + ..set_default_space PORE_SPACE_SEEPROM + SbeXipHeader SBE_SEEPROM_MAGIC, 0xFFF00000, 0xFFF00C78, _sbe_base_size + + // Create the .fixed section + .proc_sbe_fixed_proc_chip + .proc_sbe_fixed_perv + .proc_sbe_fixed_core + .proc_sbe_fixed_ex + .proc_sbe_fixed_eq diff --git a/src/ppe/sbe/image/fapi_sbe_common.H b/src/ppe/sbe/image/fapi_sbe_common.H new file mode 100644 index 0000000..aebd089 --- /dev/null +++ b/src/ppe/sbe/image/fapi_sbe_common.H @@ -0,0 +1,71 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/image/fapi_sbe_common.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file fapi_sbe_common.H +/// \brief provides several preprocessor macros used functions in fixed secion. +/// +/// Several preprocessor macros are required to have different definitions in +/// C, C++ and SBE assembly procedures. These common forms are collected here. + +#ifndef __FAPI_SBE_COMMON_H +#define __FAPI_SBE_COMMON_H + +/// Several preprocessor macros are required to have different definitions in +/// C, C++ and SBE assembly procedures. These common forms are collected here. + +#if defined __ASSEMBLER__ + +#define CONST_UINT8_T(name, expr) .set name, (expr) +#define CONST_UINT32_T(name, expr) .set name, (expr) +#define CONST_UINT64_T(name, expr) .set name, (expr) + +#define ULL(x) x + +#elif defined __cplusplus + +#include <stdint.h> + +#define CONST_UINT8_T(name, expr) const uint8_t name = (expr); +#define CONST_UINT32_T(name, expr) const uint32_t name = (expr); +#define CONST_UINT64_T(name, expr) const uint64_t name = (expr); + +#define ULL(x) x##ull + +#else // C code + +// CONST_UINT[8,3,64]_T() can't be used in C code/headers; Use +// +// #define <symbol> <value> [ or ULL(<value>) for 64-bit constants + +#define ULL(x) x##ull + +#endif // __ASSEMBLER__ + +#endif // __FAPI_SBE_COMMON_H diff --git a/src/ppe/sbe/image/img_defs.mk b/src/ppe/sbe/image/img_defs.mk new file mode 100644 index 0000000..240c5db --- /dev/null +++ b/src/ppe/sbe/image/img_defs.mk @@ -0,0 +1,336 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/sbe/image/img_defs.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# Make header for SBE image build +# +# Settings to for SBE image file build +# +# IMG_INCLUDES : Aplication-specific header search paths +# +# DEFS : A string of -D<symbol>[=<value>] to control compilation +# +# PK : Default ..; The path to the PK source code. +# The default is set for building the PK +# subdirectories. +# +# PK_THREAD_SUPPORT : (0/1, default 1); Compile PK thread and +# semaphore suppprt +# +# PK_TIMER_SUPPORT : (0/1, default 1); Compile PK timer suppprt +# +# GCC-O-LEVEL : The optimization level passed to GCC (default -Os). May +# also be defined empty (GCC-O-LEVEL=) to disable +# optimization. This variable can also be used to pass +# any other non-default setting to GCC, e.g. +# make GCC-O-LEVEL="-Os -fno-branch-count-reg" +# +# GCC-TOOL-PREFIX : The full path (including executable file prefixes) to +# the GCC cross-development tools to use. The default is +# "ppcnf-mcp5-" +# +# CTEPATH : This variable defaults to the afs/awd CTE tool +# installation - The PORE binutils are stored there. If +# you are not in Austin be sure to define CTEPATH in +# your .profile. +# +# OBJDIR : target directory for all generated files + +IMAGE_NAME := sbe_main + +PPE_TYPE := std + +ifndef IMAGE_SRCDIR +export IMAGE_SRCDIR = $(abspath .) +endif + +ifndef CACHE_SRCDIR +export CACHE_SRCDIR = $(abspath ../../hwp/cache) +endif + +ifndef CORE_SRCDIR +export CORE_SRCDIR = $(abspath ../../hwp/core) +endif + +ifndef PERV_SRCDIR +export PERV_SRCDIR = $(abspath ../../hwp/perv) +endif + +ifndef HWPLIB_SRCDIR +export HWPLIB_SRCDIR = $(abspath ../../hwp/lib) + +endif + +ifndef IMG_INCLUDES +export IMG_INCLUDES = -I$(IMAGE_SRCDIR) -I$(CACHE_SRCDIR) -I$(CORE_SRCDIR) + +endif + +ifndef IMG_INCLUDES +export IMG_INCLUDES = -I$(IMAGE_SRCDIR) -I$(CACHE_SRCDIR) -I$(CORE_SRCDIR) +endif +ifndef BASE_OBJDIR +export BASE_OBJDIR = $(abspath ../obj) +endif + +export IMG_OBJDIR = $(BASE_OBJDIR)/$(IMAGE_NAME) + +ifndef PK_SRCDIR +export PK_SRCDIR = $(abspath ../../pk) +endif + +ifndef TOOLS_ATTR_DIR +export TOOLS_ATTR_DIR = $(abspath ../../tools/scripts) +endif + + + +ifndef GCC-TOOL-PREFIX +GCC-TOOL-PREFIX = $(CTEPATH)/tools/gcc405lin/prod/usr/bin/powerpc-linux- +endif + + +ifndef P2P_SRCDIR +export P2P_SRCDIR = $(abspath ../../tools/PowerPCtoPPE) +endif + +ifndef PPETRACEPP_DIR +export PPETRACEPP_DIR = $(abspath ../../tools/ppetracepp) +endif + +ifndef PLAT_FAPI2_DIR +export PLAT_FAPI2_DIR = $(abspath ../plat) +endif + + +ifndef PPE_FAPI2_DIR +export PPE_FAPI2_DIR = $(abspath ../../hwpf/plat) +endif + +ifndef BASE_FAPI2_DIR +export BASE_FAPI2_DIR = $(abspath /afs/awd/projects/eclipz/lab/p8/u/rembold/ekbgit/hwpf/fapi2) +endif + + +ifndef CC_ROOT +export CC_ROOT = ${CTEPATH}/tools/gcc405lin/prod +endif + + +ifndef GCC-TOOL-PREFIX +GCC-TOOL-PREFIX = ${CC_ROOT}/usr/bin/powerpc-linux- +endif + +ifndef BINUTILS-TOOL-PREFIX +BINUTILS-TOOL-PREFIX = $(CTEPATH)/tools/ppetools/prod/powerpc-eabi/bin/ +endif + +OBJDIR = $(BASE_OBJDIR)$(SUB_OBJDIR) + +CC_ASM = $(GCC-TOOL-PREFIX)gcc +TCC = $(PPETRACEPP_DIR)/ppetracepp $(GCC-TOOL-PREFIX)g++ +CC = $(PPETRACEPP_DIR)/ppetracepp $(GCC-TOOL-PREFIX)gcc +AS = $(BINUTILS-TOOL-PREFIX)as +AR = $(BINUTILS-TOOL-PREFIX)ar +LD = $(BINUTILS-TOOL-PREFIX)ld +OBJDUMP = $(BINUTILS-TOOL-PREFIX)objdump +OBJCOPY = $(BINUTILS-TOOL-PREFIX)objcopy +TCPP = $(PPETRACEPP_DIR)/ppetracepp $(GCC-TOOL-PREFIX)gcc +THASH = $(PPETRACEPP_DIR)/tracehash.pl +CPP = $(GCC-TOOL-PREFIX)gcc + +ifdef P2P_ENABLE +PCP = $(P2P_SRCDIR)/ppc-ppe-pcp.py +endif + + +ifndef CTEPATH +$(warning The CTEPATH variable is not defined; Defaulting to /afs/awd) +export CTEPATH = /afs/awd/projects/cte +endif + +ifeq "$(PK_TIMER_SUPPORT)" "" +PK_TIMER_SUPPORT = 1 +endif + +ifeq "$(PK_THREAD_SUPPORT)" "" +PK_THREAD_SUPPORT = 1 +endif + +ifeq "$(PK_TRACE_SUPPORT)" "" +PK_TRACE_SUPPORT = 1 +endif + +# Generate a 16bit trace string hash prefix value based on the name of this image. This will form +# the upper 16 bits of the 32 bit trace hash values. +ifndef PK_TRACE_HASH_PREFIX +PK_TRACE_HASH_PREFIX := $(shell echo $(IMAGE_NAME) | md5sum | cut -c1-4 | xargs -i printf "%d" 0x{}) +endif + + +ifndef GCC-O-LEVEL +#GCC-O-LEVEL = -Os +#GCC-O-LEVEL = -O -g +GCC-O-LEVEL = -O +endif + +GCC-DEFS += -DIMAGE_NAME=$(IMAGE_NAME) +GCC-DEFS += -DPK_TIMER_SUPPORT=$(PK_TIMER_SUPPORT) +GCC-DEFS += -DPK_THREAD_SUPPORT=$(PK_THREAD_SUPPORT) +GCC-DEFS += -DPK_TRACE_SUPPORT=$(PK_TRACE_SUPPORT) +GCC-DEFS += -DPK_TRACE_HASH_PREFIX=$(PK_TRACE_HASH_PREFIX) +GCC-DEFS += -D__PK__=1 +GCC-DEFS += -D__SBE__=1 +DEFS += $(GCC-DEFS) +export LD_LIBRARY_PATH = /afs/awd.austin.ibm.com/proj/p3/cte/tools/gcc405lin/vol1/usr/lib + +############################################################################ + + +INCLUDES += $(IMG_INCLUDES) \ + -I$(IMAGE_SRCDIR)/../../../include \ + -I$(PLAT_FAPI2_DIR)/include \ + -I$(PPE_FAPI2_DIR)/include \ + -I$(BASE_FAPI2_DIR)/include \ + -I$(PK_SRCDIR)/../include \ + -I$(PK_SRCDIR)/$(PPE_TYPE) \ + -I$(PK_SRCDIR)/../include \ + -I$(PK_SRCDIR)/kernel \ + -I$(PK_SRCDIR)/ppe \ + -I$(PK_SRCDIR)/ppe42 \ + -I$(PK_SRCDIR)/trace + +PIPE-CFLAGS = -pipe -Wa,-m405 + +GCC-CFLAGS += -g -Wall -Werror -Wno-error=unused-label \ + -msoft-float -mcpu=405 -mmulhw \ + -meabi -msdata=eabi \ + -ffreestanding \ + -fno-common \ + -fsigned-char \ + -fno-inline-functions-called-once \ + -ffixed-r11 \ + -ffixed-r12 \ + -ffixed-r14 \ + -ffixed-r15 \ + -ffixed-r16 \ + -ffixed-r17 \ + -ffixed-r18 \ + -ffixed-r19 \ + -ffixed-r20 \ + -ffixed-r21 \ + -ffixed-r22 \ + -ffixed-r23 \ + -ffixed-r24 \ + -ffixed-r25 \ + -ffixed-r26 \ + -ffixed-r27 \ + -ffixed-cr1 \ + -ffixed-cr2 \ + -ffixed-cr3 \ + -ffixed-cr4 \ + -ffixed-cr5 \ + -ffixed-cr6 \ + -ffixed-cr7 + + +CFLAGS = -c $(GCC-CFLAGS) $(PIPE-CFLAGS) $(GCC-O-LEVEL) $(INCLUDES) + + +CPPFLAGS = -E -std=c++11 +#CPPFLAGS = -E + +ASFLAGS = -mppe42 + +ifdef P2P_ENABLE +#use this to disable optimizations (fused compare/branch etc.) +PCP-FLAG = + +#use this to enable optimizations +#PCP-FLAG = +endif +############################################################################ + +#override the GNU Make implicit rule for going from a .C to a .o +%.o: %.C + +$(OBJDIR)/%.s: %.C + $(TCC) $(PPE-CFLAGS) $(DEFS) -S -std=c++11 -o $@ $< + + +#override the GNU Make implicit rule for going from a .c to a .o +%.o: %.c + +$(OBJDIR)/%.s: %.c + $(CC) $(PPE-CFLAGS) $(DEFS) -S -o $@ $< + +#override the GNU Make implicit rule for going from a .S to a .o +%.o: %.S + +$(OBJDIR)/%.s: %.S + $(TCPP) $(PPE-CFLAGS) $(DEFS) $(CPPFLAGS) -o $@ $< +.PRECIOUS: $(OBJDIR)/%.s + +ifndef P2P_ENABLE + +$(OBJDIR)/%.o: $(OBJDIR)/%.s + $(AS) $(ASFLAGS) -o $@ $< + +else + +$(OBJDIR)/%.es: $(OBJDIR)/%.s + $(PCP) $(PCP-FLAG) -f $< +.PRECIOUS: $(OBJDIR)/%.es + +$(OBJDIR)/%.o: $(OBJDIR)/%.es + $(AS) $(ASFLAGS) -o $@ $< + +endif + +# From the GNU 'Make' manual - these scripts uses the preprocessor to +# create dependency files (*.d), then mungs them slightly to make them +# work as Make targets. The *.d files are include-ed in the +# subdirectory Makefiles. + +$(OBJDIR)/%.d: %.C + @set -e; rm -f $@; \ + echo -n "$(OBJDIR)/" > $@.$$$$; \ + $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) $(DEFS) $< >> $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +$(OBJDIR)/%.d: %.c + @set -e; rm -f $@; \ + echo -n "$(OBJDIR)/" > $@.$$$$; \ + echo "$(INCLUDES)"; \ + $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) $(DEFS) $< >> $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +$(OBJDIR)/%.d: %.S + @set -e; rm -f $@; \ + echo -n "$(OBJDIR)/" > $@.$$$$; \ + $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) $(DEFS) $< >> $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + diff --git a/src/ppe/sbe/image/link.cmd b/src/ppe/sbe/image/link.cmd new file mode 100644 index 0000000..8c75f1c --- /dev/null +++ b/src/ppe/sbe/image/link.cmd @@ -0,0 +1,115 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/image/link.cmd $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +// Need to do this so that elf32-powerpc is not modified! +#undef powerpc + +#ifndef INITIAL_STACK_SIZE +#define INITIAL_STACK_SIZE 256 +#endif + +OUTPUT_FORMAT(elf32-powerpc); + +SECTIONS +{ + . = 0xfff00000; + _sbe_base_origin = . - 0; + //////////////////////////////// + // Header + //////////////////////////////// + . = ALIGN(1); _header_origin = .; _header_offset = . - _sbe_base_origin; .header . : { *(.header) } _header_size = . - _header_origin; + + //////////////////////////////// + // FIXED + //////////////////////////////// + . = ALIGN(512); _fixed_origin = .; _fixed_offset = . - _sbe_base_origin; .fixed . : { *(.fixed) } _fixed_size = . - _fixed_origin; + + //////////////////////////////// + // FIXED_TOC + //////////////////////////////// + . = ALIGN(8); _fixed_toc_origin = .; _fixed_toc_offset = . - _sbe_base_origin; .fixed_toc . : { *(.fixed_toc) } _fixed_toc_size = . - _fixed_toc_origin; + + //////////////////////////////// + // IPL_TEXT + //////////////////////////////// + . = ALIGN(4); _ipl_text_origin = .; _ipl_text_offset = . - _sbe_base_origin; .ipl_text . : { *(.ipl_text) } _ipl_text_size = . - _ipl_text_origin; + + //////////////////////////////// + // IPL_DATA + //////////////////////////////// + . = ALIGN(8); _ipl_data_origin = .; _ipl_data_offset = . - _sbe_base_origin; .ipl_data . : { *(.ipl_data) } _ipl_data_size = . - _ipl_data_origin; + + //////////////////////////////// + // TEXT + //////////////////////////////// + . = ALIGN(4); _text_origin = .; _text_offset = . - _sbe_base_origin; .text . : {. = ALIGN(512); *(.vectors) *(.text) *(.eh_frame) } _text_size = . - _text_origin; + + //////////////////////////////// + // DATA + //////////////////////////////// + . = ALIGN(8); _data_origin = .; _data_offset = . - _sbe_base_origin; .data . : { *(.data) *(.comment) *(.rodata*)} _data_size = . - _data_origin; + + //////////////////////////////// + // TOC + //////////////////////////////// + . = ALIGN(4); _toc_origin = .; _toc_offset = . - _sbe_base_origin; .toc . : { *(.toc) } _toc_size = . - _toc_origin; + + //////////////////////////////// + // STRING + //////////////////////////////// + . = ALIGN(1); _strings_origin = .; _strings_offset = . - _sbe_base_origin; .strings . : { *(.strings) } _strings_size = . - _strings_origin; + +// . = ALIGN(8); +// _sbe_base_size = . - _sbe_base_origin; +// _sbe_base_end = . - 0; + + + _RODATA_SECTION_BASE = .; + + + _SDA2_BASE_ = .; + + _RODATA_SECTION_SIZE = . - _RODATA_SECTION_BASE; + + // SDA sections .sdata and .sbss must be adjacent to each + // other. Our SDATA sections are small so we'll use strictly positive + // offsets. + + _SDA_BASE_ = .; + + .sbss . : { *(.sbss) } + .sdata . : { *(.sdata) } + + + _PK_INITIAL_STACK_LIMIT = .; + . = . + INITIAL_STACK_SIZE; + _PK_INITIAL_STACK = . - 1; + + + . = ALIGN(8); + _sbe_base_size = . - _sbe_base_origin; + _sbe_base_end = . - 0; + + +} diff --git a/src/ppe/sbe/image/p9_sbe.H b/src/ppe/sbe/image/p9_sbe.H new file mode 100644 index 0000000..b5118c1 --- /dev/null +++ b/src/ppe/sbe/image/p9_sbe.H @@ -0,0 +1,53 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/image/p9_sbe.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __P9_SBE_H +#define __P9_SBE_H + +/// \file p9_sbe.H +/// \brief A header to be included into all SBE assembler files and C++ +/// hardware procedures that interact with SBE images. +/// +/// This header #include-s all generally useful headers required for SBE code +/// development as well as defining other needed facilities. Note that any +/// sub-includes must be done in an assembler-safe way. + +#include "sbe_common.H" +//#include "p9_scom_addresses.H" +//#include "p9_istep_num.H" + +// The #include of fapiHwpReturnCodes.H must be made here (instead of in +// sbe_common.H) to guarantee that the P9-local copy is used. +//#include "fapiHwpReturnCodes.H" + +#ifdef __ASSEMBLER__ + + // p9_sbe.H 'recursively' inserts itself into any hook code extracted + // from an assembly context that includes p9_sbe.H. + + ##`#include "p9_sbe.H" + +#endif // __ASSEMBLER__ + +#endif // __P9_SBE_H diff --git a/src/ppe/sbe/image/proc_sbe_fixed.H b/src/ppe/sbe/image/proc_sbe_fixed.H new file mode 100644 index 0000000..304b868 --- /dev/null +++ b/src/ppe/sbe/image/proc_sbe_fixed.H @@ -0,0 +1,189 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/image/proc_sbe_fixed.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file proc_sbe_fixed.H +/// \brief Define the layout of fixed-position data in the P9 SBE reference +/// and IPL images +/// +/// Contains struct ProcSbeFixed which contains functions, rings and +/// attributes whose pointers are stored in the fixed and fixed_toc section +/// +/// This file defines the layout of the special .fixed data section of P9 SBE +/// reference and IPL images. The .fixed section is guaranteed to appear at a +/// fixed offset from the beginning of the image, containing data required to +/// be manipulated when images are resident in non-volatile memories, thereby +/// avoiding having to search the TOC. Data manipulated during in-memory image +/// processing can always be easily located using the SBE-XIP TOC APIs. All +/// of the data stored in .fixed can also still be referenced via the SBE-XIP +/// TOC. +/// +/// This header file can be #include-ed into either C or SBE assembly language +/// source code. In C, it creates simple structures 'ProcChipAttributes', +/// 'PervAttributes', 'CoreAttributes', 'EQAttributes' and 'EXAttributes' that +/// contain attribute information that are sized per XML definition per entry. +/// +/// PPE image data is always stored big-endian, so applications on little-endian +/// hosts will need to perform the appropriate endian converison when reading or +/// writing images via this header. +/// +/// In assembler code, this header creates macros '.proc_sbe_fixed_proc_chip', +/// '.proc_sbe_fixed_perv', '.proc_sbe_fixed_core', '.proc_sbe_fixed_ex', +/// '.proc_sbe_fixed_eq', that is expanded exactly once in the file +/// 'sbe_base_header.S', creating the actual data allocation of the data +/// equivalent to the C structure. Assembler code references the data symbols +/// as normal. +/// +/// To simplify programming a 'mini-TOC' is also provided for this data in +/// the .fixed_toc section. This section is comprised of SbeXipHashedToc +/// structures. When a symbol is indedxed in .fixed, a blank SbeXipHashedToc +/// stucture is added to .fixed_toc. During image normalization the array of +/// SbeXipHashedToc is filled in as each symbol in .fixed is re-indexed into +/// .fixed_toc. + +#ifndef __PROC_SBE_FIXED_H__ +#define __PROC_SBE_FIXED_H__ + +#include "p9_sbe.H" +#include "plat_target_parms.H" +#include "fapi2AttributeIds.H" + + +#ifdef __ASSEMBLER__ + .macro .proc_sbe_fixed_proc_chip + .section .fixed, "a", @progbits + .balign 8 + .global G_proc_chip_attributes +G_proc_chip_attributes: +#else +extern "C" { +namespace fapi2attr { +typedef struct ProcChipAttributes_t { +#endif + +#include "proc_sbe_fixed_proc_chip.H" + +#ifdef __ASSEMBLER__ + .endm +#else +} ProcChipAttributes; +} // fapi2 +} // C +#endif + +/// +/// Pervasive Target Attributes +#ifdef __ASSEMBLER__ + .macro .proc_sbe_fixed_perv + .section .fixed, "a", @progbits + .balign 8 + .global G_perv_attributes +G_perv_attributes: +#else +namespace fapi2attr { +typedef struct PervAttributes_t { +#endif + +#include "proc_sbe_fixed_perv.H" + +#ifdef __ASSEMBLER__ + .endm +#else +} PervAttributes; +} // fapi2 +#endif + +/// +/// Core (EC) Target Attributes +#ifdef __ASSEMBLER__ + .macro .proc_sbe_fixed_core + .section .fixed, "a", @progbits + .balign 8 + .global G_core_attributes +G_core_attributes: +#else +namespace fapi2attr { +typedef struct CoreAttributes_t { +#endif + +#include "proc_sbe_fixed_core.H" + +#ifdef __ASSEMBLER__ + .endm +#else +} CoreAttributes; +} // fapi2 +#endif + +/// +/// EX Target Attributes +#ifdef __ASSEMBLER__ + .macro .proc_sbe_fixed_ex + .section .fixed, "a", @progbits + .balign 8 + .global G_ex_attributes +G_ex_attributes: +#else +namespace fapi2attr { +typedef struct EXAttributes_t { +#endif + +#include "proc_sbe_fixed_ex.H" + +#ifdef __ASSEMBLER__ + .endm +#else +} EXAttributes; +} // fapi2 +#endif + +/// +/// EQ Target Attributes +#ifdef __ASSEMBLER__ + .macro .proc_sbe_fixed_eq + .section .fixed, "a", @progbits + .balign 8 + .global G_eq_attributes +G_eq_attributes: +#else +namespace fapi2attr { +typedef struct EQAttributes_t { +#endif + +#include "proc_sbe_fixed_eq.H" + +#ifdef __ASSEMBLER__ + .endm +#else +} EQAttributes; +} // fapi2 +#endif + + +#endif // __PROC_SBE_FIXED_H__ diff --git a/src/ppe/sbe/image/sbe_common.H b/src/ppe/sbe/image/sbe_common.H new file mode 100644 index 0000000..a4489df --- /dev/null +++ b/src/ppe/sbe/image/sbe_common.H @@ -0,0 +1,601 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/image/sbe_common.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __SBE_COMMON_H +#define __SBE_COMMON_H + +// $Id: Exp $ + +/// \file sbe_common.H + +/// \brief This header contains #include-s and macro definitions common to P8 +/// and Centaur SBE code development. It is #include-ed into p8_sbe.H and +/// cen_sbe.H which have other setup specific to each environment. + + +#include "sbe_link.H" +#include "sbe_xip_image.h" +//#include "sbe_xip_header.H" + +/// Macros for generating the .fixed section +/// +/// The CPP macros PROC_SBE_FIXED_UINT64[_VECTOR] generate equivalent code +/// depending on whether they are being called from assembler (where they +/// actually create the .fixed section data) or from C (where they specifiy a +/// C-structure form of the contents of the .fixed section. +/// +/// In assembler each invocation also creates space in the .fixed_toc section +/// for a fixed TOC entry. Unlike the normal TOC no data is generated for +/// .fixed_toc by the data declaration. Instead, the fixed TOC table is +/// filled in during image normalization by normalizeToc (sbe_xip_image.c) +/// which requires that there be one and only one fixed TOC entery allocated +/// per TOC entry referencing the .fixed section. This means that in the +/// current implementation it is not possible to create .fixed_toc entries +/// for addresses or for data stored in sections other than .fixed. + +#ifdef __ASSEMBLER__ + + .macro proc_sbe_fixed_uint8, symbol:req, tnumber=1, elements=1 + .global \symbol +\symbol\(): + .rept ((\tnumber)*(\elements)) + .byte 0 + .endr + + .xip_toc \symbol, SBE_XIP_UINT8, \symbol, (\elements) + + .pushsection .fixed_toc + .space 8 + .popsection + + .endm + + .macro proc_sbe_fixed_int8, symbol:req, tnumber=1, elements=1 + .global \symbol +\symbol\(): + .rept ((\tnumber)*(\elements)) + .byte 0 + .endr + + .xip_toc \symbol, SBE_XIP_INT8, \symbol, (\elements) + + .pushsection .fixed_toc + .space 8 + .popsection + + .endm + + .macro proc_sbe_fixed_uint16, symbol:req, tnumber=1, elements=1 + .balign 2 + .global \symbol +\symbol\(): + + .rept ((\tnumber)*(\elements)) + .long 0 + .endr + + .xip_toc \symbol, SBE_XIP_UINT16, \symbol, (\elements) + + .pushsection .fixed_toc + .space 8 + .popsection + + .endm + + .macro proc_sbe_fixed_int16, symbol:req, tnumber=1, elements=1 + .balign 2 + .global \symbol +\symbol\(): + + .rept ((\tnumber)*(\elements)) + .long 0 + .endr + + .xip_toc \symbol, SBE_XIP_INT16, \symbol, (\elements) + + .pushsection .fixed_toc + .space 8 + .popsection + + .endm + + .macro proc_sbe_fixed_uint32, symbol:req, tnumber=1, elements=1 + .balign 4 + .global \symbol +\symbol\(): + + .rept ((\tnumber)*(\elements)) + .long 0 + .endr + + .xip_toc \symbol, SBE_XIP_UINT32, \symbol, (\elements) + + .pushsection .fixed_toc + .space 8 + .popsection + + .endm + + .macro proc_sbe_fixed_int32, symbol:req, tnumber=1, elements=1 + .balign 4 + .global \symbol +\symbol\(): + + .rept ((\tnumber)*(\elements)) + .long 0 + .endr + + .xip_toc \symbol, SBE_XIP_INT32, \symbol, (\elements) + + .pushsection .fixed_toc + .space 8 + .popsection + + .endm + + .macro proc_sbe_fixed_uint64, symbol:req, tnumber=1, elements=1 + .balign 8 + .global \symbol +\symbol\(): + .rept ((\tnumber)*(\elements)) + .quad 0 + .endr + + .xip_toc \symbol, SBE_XIP_UINT64, \symbol, (\elements) + + .pushsection .fixed_toc + .space 8 + .popsection + + .endm + + .macro proc_sbe_fixed_int64, symbol:req, tnumber=1, elements=1 + .balign 8 + .global \symbol +\symbol\(): + .rept ((\tnumber)*(\elements)) + .quad 0 + .endr + + .xip_toc \symbol, SBE_XIP_INT64, \symbol, (\elements) + + .pushsection .fixed_toc + .space 8 + .popsection + + .endm + + .macro proc_sbe_fixed_quadia, symbol:req, space:req, address:req + .global \symbol +\symbol\(): + .quadia (\space), (\address) + + .xip_toc \symbol, SBE_XIP_UINT64, \symbol + + .pushsection .fixed_toc + .space 8 + .popsection + + .endm + + +#define PROC_SBE_FIXED_UINT8(symbol) \ + proc_sbe_fixed_uint8 symbol + +#define PROC_SBE_FIXED_INT8(symbol) \ + proc_sbe_fixed_int8 symbol + +#define PROC_SBE_FIXED_UINT16(symbol) \ + proc_sbe_fixed_uint16 symbol + +#define PROC_SBE_FIXED_INT16(symbol) \ + proc_sbe_fixed_int16 symbol + +#define PROC_SBE_FIXED_UINT32(symbol) \ + proc_sbe_fixed_uint32 symbol + +#define PROC_SBE_FIXED_INT32(symbol) \ + proc_sbe_fixed_int32 symbol + +#define PROC_SBE_FIXED_UINT64(symbol) \ + proc_sbe_fixed_uint64 symbol + +#define PROC_SBE_FIXED_INT64(symbol) \ + proc_sbe_fixed_int64 symbol + +#define PROC_SBE_FIXED_UINT8_VECTOR(symbol, elements) \ + proc_sbe_fixed_uint8 symbol, elements + +#define PROC_SBE_FIXED_INT8_VECTOR(symbol, elements) \ + proc_sbe_fixed_int8 symbol, elements + +#define PROC_SBE_FIXED_UINT16_VECTOR(symbol, elements) \ + proc_sbe_fixed_uint16 symbol, elements + +#define PROC_SBE_FIXED_INT16_VECTOR(symbol, elements) \ + proc_sbe_fixed_int16 symbol, elements + +#define PROC_SBE_FIXED_UINT32_VECTOR(symbol, elements) \ + proc_sbe_fixed_uint32 symbol, elements + +#define PROC_SBE_FIXED_INT32_VECTOR(symbol, elements) \ + proc_sbe_fixed_int32 symbol, elements + +#define PROC_SBE_FIXED_UINT64_VECTOR(symbol, elements) \ + proc_sbe_fixed_uint64 symbol, elements + +#define PROC_SBE_FIXED_INT64_VECTOR(symbol, elements) \ + proc_sbe_fixed_int64 symbol, elements + +#define PROC_SBE_FIXED_UINT8_VECTOR_2(symbol, dim1, dim2 ) \ + proc_sbe_fixed_uint8 symbol, dim1 * dim2 + +#define PROC_SBE_FIXED_INT8_VECTOR_2(symbol, dim1, dim2 ) \ + proc_sbe_fixed_int8 symbol, dim1 * dim2 + +#define PROC_SBE_FIXED_UINT16_VECTOR_2(symbol, dim1, dim2 ) \ + proc_sbe_fixed_uint16 symbol, dim1 * dim2 + +#define PROC_SBE_FIXED_INT16_VECTOR_2(symbol, dim1, dim2 ) \ + proc_sbe_fixed_int16 symbol, dim1 * dim2 + +#define PROC_SBE_FIXED_UINT32_VECTOR_2(symbol, dim1, dim2 ) \ + proc_sbe_fixed_uint32 symbol, dim1 * dim2 + +#define PROC_SBE_FIXED_INT32_VECTOR_2(symbol, dim1, dim2 ) \ + proc_sbe_fixed_int32 symbol, dim1 * dim2 + +#define PROC_SBE_FIXED_UINT64_VECTOR_2(symbol, dim1, dim2 ) \ + proc_sbe_fixed_uint64 symbol, dim1 * dim2 + +#define PROC_SBE_FIXED_INT64_VECTOR_2(symbol, dim1, dim2 ) \ + proc_sbe_fixed_int64 symbol, dim1 * dim2 + +#define PROC_SBE_FIXED_UINT8_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint8 symbol, dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_INT8_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint8 symbol, dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_UINT16_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint16 symbol, dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_INT16_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint16 symbol, dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_UINT32_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint32 symbol, dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_INT32_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint32 symbol, dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_UINT64_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint64 symbol, dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_INT64_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint64 symbol, dim1 * dim2 * dim3 + +// Non-Chip Target Attributes + +#define PROC_SBE_FIXED_TARGET_UINT8(symbol, tnumber) \ + proc_sbe_fixed_uint8 symbol, tnumber + +#define PROC_SBE_FIXED_TARGET_INT8(symbol, tnumber) \ + proc_sbe_fixed_int8 symbol, tnumber + +#define PROC_SBE_FIXED_TARGET_UINT16(symbol, tnumber) \ + proc_sbe_fixed_uint16 symbol, tnumber + +#define PROC_SBE_FIXED_TARGET_INT16(symbol, tnumber) \ + proc_sbe_fixed_int16 symbol, tnumber + +#define PROC_SBE_FIXED_TARGET_UINT32(symbol, tnumber) \ + proc_sbe_fixed_uint32 symbol, tnumber + +#define PROC_SBE_FIXED_TARGET_INT32(symbol, tnumber) \ + proc_sbe_fixed_int32 symbol, tnumber + +#define PROC_SBE_FIXED_TARGET_UINT64(symbol, tnumber) \ + proc_sbe_fixed_uint64 symbol, tnumber + +#define PROC_SBE_FIXED_TARGET_INT64(symbol, tnumber) \ + proc_sbe_fixed_int64 symbol, tnumber + +#define PROC_SBE_FIXED_TARGET_UINT8_VECTOR(symbol, tnumber, elements) \ + proc_sbe_fixed_uint8 symbol, tnumber * elements + +#define PROC_SBE_FIXED_TARGET_INT8_VECTOR(symbol, tnumber, elements) \ + proc_sbe_fixed_int8 symbol, tnumber * elements + +#define PROC_SBE_FIXED_TARGET_UINT16_VECTOR(symbol, tnumber, elements) \ + proc_sbe_fixed_uint16 symbol, tnumber * elements + +#define PROC_SBE_FIXED_TARGET_INT16_VECTOR(symbol, tnumber, elements) \ + proc_sbe_fixed_int16 symbol, tnumber * elements + +#define PROC_SBE_FIXED_TARGET_UINT32_VECTOR(symbol, tnumber, elements) \ + proc_sbe_fixed_uint32 symbol, tnumber * elements + +#define PROC_SBE_FIXED_TARGET_INT32_VECTOR(symbol, tnumber, elements) \ + proc_sbe_fixed_int32 symbol, tnumber * elements + +#define PROC_SBE_FIXED_TARGET_UINT64_VECTOR(symbol, tnumber, elements) \ + proc_sbe_fixed_uint64 symbol, tnumber * elements + +#define PROC_SBE_FIXED_TARGET_INT64_VECTOR(symbol, tnumber, elements) \ + proc_sbe_fixed_int64 symbol, tnumber * elements + +#define PROC_SBE_FIXED_TARGET_UINT8_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + proc_sbe_fixed_uint8 symbol, tnumber * dim1 * dim2 + +#define PROC_SBE_FIXED_TARGET_INT8_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + proc_sbe_fixed_int8 symbol, tnumber * dim1 * dim2 + +#define PROC_SBE_FIXED_TARGET_UINT16_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + proc_sbe_fixed_uint16 symbol, tnumber * dim1 * dim2 + +#define PROC_SBE_FIXED_TARGET_INT16_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + proc_sbe_fixed_int16 symbol, tnumber * dim1 * dim2 + +#define PROC_SBE_FIXED_TARGET_UINT32_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + proc_sbe_fixed_uint32 symbol, tnumber * dim1 * dim2 + +#define PROC_SBE_FIXED_TARGET_INT32_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + proc_sbe_fixed_int32 symbol, tnumber * dim1 * dim2 + +#define PROC_SBE_FIXED_TARGET_UINT64_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + proc_sbe_fixed_uint64 symbol, tnumber * dim1 * dim2 + +#define PROC_SBE_FIXED_TARGET_INT64_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + proc_sbe_fixed_int64 symbol, tnumber * dim1 * dim2 + +#define PROC_SBE_FIXED_TARGET_UINT8_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint8 symbol, tnumber * dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_TARGET_INT8_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint8 symbol, tnumber * dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_TARGET_UINT16_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint16 symbol, tnumber * dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_TARGET_INT16_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint16 symbol, tnumber * dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_TARGET_UINT32_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint32 symbol, tnumber * dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_TARGET_INT32_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint32 symbol, tnumber * dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_TARGET_UINT64_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint64 symbol, tnumber * dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_TARGET_INT64_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + proc_sbe_fixed_uint64 symbol, tnumber * dim1 * dim2 * dim3 + +#define PROC_SBE_FIXED_QUADIA(symbol, space, address) \ + proc_sbe_fixed_quadia symbol, (space), (address) + + +#else // __ASSEMBLER__ (eg the C portion) + +#define PROC_SBE_FIXED_UINT8(symbol) \ + uint8_t symbol + +#define PROC_SBE_FIXED_INT8(symbol) \ + int8_t symbol + +#define PROC_SBE_FIXED_UINT16(symbol) \ + uint16_t symbol + +#define PROC_SBE_FIXED_INT16(symbol) \ + int16_t symbol + +#define PROC_SBE_FIXED_UINT32(symbol) \ + uint32_t symbol + +#define PROC_SBE_FIXED_INT32(symbol) \ + int32_t symbol + +#define PROC_SBE_FIXED_UINT64(symbol) \ + uint64_t symbol + +#define PROC_SBE_FIXED_INT64(symbol) \ + int64_t symbol + +#define PROC_SBE_FIXED_UINT8_VECTOR(symbol, elements) \ + uint8_t symbol[elements] + +#define PROC_SBE_FIXED_INT8_VECTOR(symbol, elements) \ + int8_t symbol[elements] + +#define PROC_SBE_FIXED_UINT16_VECTOR(symbol, elements) \ + uint16_t symbol[elements] + +#define PROC_SBE_FIXED_INT16_VECTOR(symbol, elements) \ + int16_t symbol[elements] + +#define PROC_SBE_FIXED_UINT32_VECTOR(symbol, elements) \ + uint32_t symbol[elements] + +#define PROC_SBE_FIXED_INT32_VECTOR(symbol, elements) \ + int32_t symbol[elements] + +#define PROC_SBE_FIXED_UINT64_VECTOR(symbol, elements) \ + uint64_t symbol[elements] + +#define PROC_SBE_FIXED_INT64_VECTOR(symbol, elements) \ + int64_t symbol[elements] + +#define PROC_SBE_FIXED_UINT8_VECTOR_2(symbol, dim1, dim2 ) \ + uint8_t symbol[dim1][dim2] + +#define PROC_SBE_FIXED_INT8_VECTOR_2(symbol, dim1, dim2 ) \ + int8_t symbol[dim1][dim2] + +#define PROC_SBE_FIXED_UINT16_VECTOR_2(symbol, dim1, dim2 ) \ + uint16_t symbol[dim1][dim2] + +#define PROC_SBE_FIXED_INT16_VECTOR_2(symbol, dim1, dim2 ) \ + int16_t symbol[dim1][dim2] + +#define PROC_SBE_FIXED_UINT32_VECTOR_2(symbol, dim1, dim2 ) \ + uint32_t symbol[dim1][dim2] + +#define PROC_SBE_FIXED_INT32_VECTOR_2(symbol, dim1, dim2 ) \ + int32_t symbol[dim1][dim2] + +#define PROC_SBE_FIXED_UINT64_VECTOR_2(symbol, dim1, dim2 ) \ + uint64_t symbol[dim1][dim2] + +#define PROC_SBE_FIXED_INT64_VECTOR_2(symbol, dim1, dim2 ) \ + int64_t symbol[dim1][dim2] + +#define PROC_SBE_FIXED_UINT8_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + uint8_t symbol[dim1][dim2][dim3] + +#define PROC_SBE_FIXED_INT8_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + int8_t symbol[dim1][dim2][dim3] + +#define PROC_SBE_FIXED_UINT16_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + uint16_t symbol[dim1][dim2][dim3] + +#define PROC_SBE_FIXED_INT16_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + int16_t symbol[dim1][dim2][dim3] + +#define PROC_SBE_FIXED_UINT32_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + uint32_t symbol[dim1][dim2][dim3] + +#define PROC_SBE_FIXED_INT32_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + int32_t symbol[dim1][dim2][dim3] + +#define PROC_SBE_FIXED_UINT64_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + uint64_t symbol[dim1][dim2][dim3] + +#define PROC_SBE_FIXED_INT64_VECTOR_3(symbol, dim1, dim2, dim3 ) \ + int64_t symbol[dim1][dim2][dim3] + +// Non-Chip Target Attributes + +#define PROC_SBE_FIXED_TARGET_UINT8(symbol, tnumber) \ + uint8_t symbol[tnumber] + +#define PROC_SBE_FIXED_TARGET_INT8(symbol, tnumber) \ + int8_t symbol[tnumber] + +#define PROC_SBE_FIXED_TARGET_UINT16(symbol, tnumber) \ + uint16_t symbol[tnumber] + +#define PROC_SBE_FIXED_TARGET_INT16(symbol, tnumber) \ + int16_t symbol[tnumber] + +#define PROC_SBE_FIXED_TARGET_UINT32(symbol, tnumber) \ + uint32_t symbol[tnumber] + +#define PROC_SBE_FIXED_TARGET_INT32(symbol, tnumber) \ + int32_t symbol[tnumber] + +#define PROC_SBE_FIXED_TARGET_UINT64(symbol, tnumber) \ + uint64_t symbol[tnumber] + +#define PROC_SBE_FIXED_TARGET_INT64(symbol, tnumber) \ + int64_t symbol[tnumber] + +#define PROC_SBE_FIXED_TARGET_UINT8_VECTOR(symbol, tnumber, elements) \ + uint8_t symbol[tnumber][elements] + +#define PROC_SBE_FIXED_TARGET_INT8_VECTOR(symbol, tnumber, elements) \ + int8_t symbol[tnumber][elements] + +#define PROC_SBE_FIXED_TARGET_UINT16_VECTOR(symbol, tnumber, elements) \ + uint16_t symbol[tnumber][elements] + +#define PROC_SBE_FIXED_TARGET_INT16_VECTOR(symbol, tnumber, elements) \ + int16_t symbol[tnumber][elements] + +#define PROC_SBE_FIXED_TARGET_UINT32_VECTOR(symbol, tnumber, elements) \ + uint32_t symbol[tnumber][elements] + +#define PROC_SBE_FIXED_TARGET_INT32_VECTOR(symbol, tnumber, elements) \ + int32_t symbol[tnumber][elements] + +#define PROC_SBE_FIXED_TARGET_UINT64_VECTOR(symbol, tnumber, elements) \ + uint64_t symbol[tnumber][elements] + +#define PROC_SBE_FIXED_TARGET_INT64_VECTOR(symbol, tnumber, elements) \ + int64_t symbol[tnumber][elements] + +#define PROC_SBE_FIXED_TARGET_UINT8_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + uint8_t symbol[tnumber][dim1][dim2] + +#define PROC_SBE_FIXED_TARGET_INT8_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + int8_t symbol[tnumber][dim1][dim2] + +#define PROC_SBE_FIXED_TARGET_UINT16_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + uint16_t symbol[tnumber][dim1][dim2] + +#define PROC_SBE_FIXED_TARGET_INT16_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + int16_t symbol[tnumber][dim1][dim2] + +#define PROC_SBE_FIXED_TARGET_UINT32_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + uint32_t symbol[tnumber][dim1][dim2] + +#define PROC_SBE_FIXED_TARGET_INT32_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + int32_t symbol[tnumber][dim1][dim2] + +#define PROC_SBE_FIXED_TARGET_UINT64_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + uint64_t symbol[tnumber][dim1][dim2] + +#define PROC_SBE_FIXED_TARGET_INT64_VECTOR_2(symbol, tnumber, dim1, dim2 ) \ + int64_t symbol[tnumber][dim1][dim2] + +#define PROC_SBE_FIXED_TARGET_UINT8_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + uint8_t symbol[tnumber][dim1][dim2][dim3] + +#define PROC_SBE_FIXED_TARGET_INT8_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + int8_t symbol[tnumber][dim1][dim2][dim3] + +#define PROC_SBE_FIXED_TARGET_UINT16_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + uint16_t symbol[tnumber][dim1][dim2][dim3] + +#define PROC_SBE_FIXED_TARGET_INT16_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + int16_t symbol[tnumber][dim1][dim2][dim3] + +#define PROC_SBE_FIXED_TARGET_UINT32_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + uint32_t symbol[tnumber][dim1][dim2][dim3] + +#define PROC_SBE_FIXED_TARGET_INT32_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + int32_t symbol[tnumber][dim1][dim2][dim3] + +#define PROC_SBE_FIXED_TARGET_UINT64_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + uint64_t symbol[tnumber][dim1][dim2][dim3] + +#define PROC_SBE_FIXED_TARGET_INT64_VECTOR_3(symbol, tnumber, dim1, dim2, dim3 ) \ + int64_t symbol[tnumber][dim1][dim2][dim3] + +#define PROC_SBE_FIXED_QUADIA(symbol, space, address) uint64_t symbol + +#endif // __ASSEMBLER__ + +#endif // __SBE_COMMON_H diff --git a/src/ppe/sbe/image/sbe_link.H b/src/ppe/sbe/image/sbe_link.H new file mode 100644 index 0000000..5635f39 --- /dev/null +++ b/src/ppe/sbe/image/sbe_link.H @@ -0,0 +1,77 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/image/sbe_link.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __SBE_LINK_H +#define __SBE_LINK_H + +// $Id: Exp $ + +/// \file sbe_link.H +/// \brief Constants required for linking SBE code images +/// +/// This header contains those cpp manifest constants required for processing +/// the linker scripts used to generate SBE code images. They may also be +/// useful for PPE assembler programming so they are included in sbe.H as +/// well. +/// +/// The link address of OTPROM code as a byte-address +/// +/// The OTPROM can be addressed both as an I2C slave and as a direct PIB +/// slave. The I2C slave is at PIB local address 0x0 and the PIB memory +/// interface is at local address 0x8000. SBE/IPL uses the PIB addressing +/// mode, so the OTPROM image is linked at 0x40000 (the byte-address +/// equivalent of 0x8000). +#define OTPROM_ORIGIN 0x40000 + +/// The amount of memory contained in each OTPROM macro +#define OTPROM_BLOCK_SIZE 4096 + +/// The amount of memory reserved for OTPROM code +/// +/// This amount is exclusive of physical OTPROM memory reserved for compressed +/// scan ring images. +#define OTPROM_CODE_SIZE (1 * OTPROM_BLOCK_SIZE) + +/// The link address of the P9 SBE Base image +#define SBE_BASE_ORIGIN 0xFFFF0000 + +/// The physical address offset where SBE-SEEPROM code is loaded +/// +/// This address *must* be a constant known to the OTPROM code. +#define SBE_SEEPROM_LOAD_ADDRESS 0x2000 + +/// The offset (in bytes) of the .fixed section in P9 SBE-XIP images +#define SBE_XIP_FIXED_OFFSET 512 + +/// The link address of the PIBMEM image +#define PIBMEM_ORIGIN 0 + +/// The amount of space available in the PIBMEM, in bytes (3KB) +#define PIBMEM_SIZE (64 * 1024) + +/// The offset (in bytes) of the .fixed section in P9 SBE-XIP images +#define SBE_XIP_FIXED_OFFSET 512 + +#endif // __SBE_LINK_H + diff --git a/src/ppe/sbe/image/sbe_xip_image.h b/src/ppe/sbe/image/sbe_xip_image.h new file mode 100644 index 0000000..9340fcb --- /dev/null +++ b/src/ppe/sbe/image/sbe_xip_image.h @@ -0,0 +1,1786 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/image/sbe_xip_image.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file sbe_xip_image.h +/// \brief definition of structs in sections +/// +/// Contains struct ProcSbeFixed which contains functions, rings and +/// attributes whose pointers are stored in the fixed and fixed_toc section +/// Everything related to creating and manipulating SBE-XIP binary images + +#ifndef __SBE_XIP_IMAGE_H +#define __SBE_XIP_IMAGE_H + +#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.H. -*- + +#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_DCRINGS 11 +#define SBE_XIP_SECTION_RINGS 12 +#define SBE_XIP_SECTION_SLW 13 +#define SBE_XIP_SECTION_FIT 14 +#define SBE_XIP_SECTION_FFDC 15 + +#define SBE_XIP_SECTIONS 16 + +/// @} + + +/// \defgroup sbe_xip_validate() ignore masks. +/// +/// These defines, when matched in sbe_xip_validate(), cause the validation +/// to skip the check of the corresponding property. The purpose is to more +/// effectively debug images that may be damaged and which have excess info +/// before or after the image. The latter will be the case when dumping the +/// image as a memory block without knowing where the image starts and ends. +/// +/// @{ + +#define SBE_XIP_IGNORE_FILE_SIZE (uint32_t)0x00000001 +#define SBE_XIP_IGNORE_ALL (uint32_t)0x80000000 + +/// @} + + +#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", \ + ".dcrings", \ + ".rings", \ + ".slw", \ + ".fit", \ + ".ffdc", \ + } + +/// 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 +/// +/// \param[in] i_maskIgnores Array of ignore bits representing which properties +/// should not be checked for in sbe_xip_validate2(). +/// +/// 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); + +int +sbe_xip_validate2(void* i_image, const uint32_t i_size, const uint32_t i_maskIgnores); + + +/// 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,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 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. +/// +/// \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 +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) +/// +/// \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 +/// 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. +/// +/// \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. +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 +/// +/// \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_poreAddress, + const char** o_rcString); + + +/// Delete a section from an SBE-XIP image 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 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. Any alignment padding of the now-last section is also +/// removed. +/// +/// \note 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); + + +#ifndef PPC_HYP + +/// 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 \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 \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 +/// +/// \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* o_size); + +#endif // PPC_HYP + + +/// 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 return value +/// is invalid in the event of a non-0 return code. +/// +/// 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. +/// +/// \note If the call fails for any reason (other than a bug in the API +/// itself) then the \a io_image data is returned unmodified. +/// +/// \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* o_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/ppe/sbe/image/topfiles.mk b/src/ppe/sbe/image/topfiles.mk new file mode 100644 index 0000000..bfcb577 --- /dev/null +++ b/src/ppe/sbe/image/topfiles.mk @@ -0,0 +1,35 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/sbe/image/topfiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +TOP-C-SOURCES = base_ppe_demo.c +TOP-CPP-SOURCES = +TOP-S-SOURCES = base_ppe_header.S + +TOP-FIXED-HEADERS += $(IMAGE_SRCDIR)/proc_sbe_fixed_perv.H +TOP-FIXED-HEADERS += $(IMAGE_SRCDIR)/proc_sbe_fixed_proc_chip.H +TOP-FIXED-HEADERS += $(IMAGE_SRCDIR)/proc_sbe_fixed_core.H +TOP-FIXED-HEADERS += $(IMAGE_SRCDIR)/proc_sbe_fixed_ex.H +TOP-FIXED-HEADERS += $(IMAGE_SRCDIR)/proc_sbe_fixed_eq.H + +TOP_OBJECTS = $(TOP-C-SOURCES:.c=.o) $(TOP-CPP-SOURCES:.C=.o) $(TOP-S-SOURCES:.S=.o) diff --git a/src/ppe/sbe/sample/Makefile b/src/ppe/sbe/sample/Makefile new file mode 100644 index 0000000..8bf74a0 --- /dev/null +++ b/src/ppe/sbe/sample/Makefile @@ -0,0 +1,100 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/sbe/sample/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +#remove this once we have a real compiler +export P2P_ENABLE = 1 + +#Pull in the definitions that affect all makefiles for this image +include img_defs.mk + +#Pull in object file names for the top directory +include topfiles.mk + +ifdef P2P_ENABLE +include $(P2P_SRCDIR)/p2pfiles.mk +endif + +PK_MAKE_DIR := $(PK_SRCDIR)/$(PPE_TYPE) +OBJS := $(addprefix $(OBJDIR)/, $(TOP_OBJECTS)) +PKLIB := $(OBJDIR)/pk/libpk.a + +LIB_DIRS = -L$(OBJDIR)/pk #-L$(OBJDIR)/commonlib +LINK_OBJS = $(OBJS) $(PKLIB) #$(COMMONLIB) +LINK_SCRIPT = $(addprefix $(OBJDIR)/, linkscript) + +ifdef P2P_ENABLE +P2PLIB := $(OBJDIR)/p2p/libp2p.a +LIB_DIRS += -L$(OBJDIR)/p2p +LINK_OBJS += $(P2PLIB) +endif + +#default target is to make a binary application image +#This removes all unecessary headers from the ELF executable +$(OBJDIR)/$(IMAGE_NAME).bin $(OBJDIR)/$(IMAGE_NAME).dis: $(OBJDIR)/$(IMAGE_NAME).out + $(OBJCOPY) -O binary $< $(OBJDIR)/$(IMAGE_NAME).bin + $(OBJDUMP) -S $< > $(OBJDIR)/$(IMAGE_NAME).dis + +#create a linked ELF executable +$(OBJDIR)/$(IMAGE_NAME).out: $(LINK_OBJS) $(LINK_SCRIPT) + $(LD) -e __system_reset -T$(LINK_SCRIPT) -Map $(OBJDIR)/$(IMAGE_NAME).map -Bstatic -o $(OBJDIR)/$(IMAGE_NAME).out $(LIB_DIRS) $(OBJS) -lpk -lp2p #-lcommon + +#pass the link command file through the C preprocessor to evaluate macros and remove comments +$(LINK_SCRIPT): link.cmd + $(CPP) -E -x c++ -P $(DEFS) link.cmd -o $(LINK_SCRIPT) + +#Create an obj directory if needed +$(LINK_OBJS) $(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +.PHONY: clean $(PKLIB) $(P2PLIB) + +#Build macro-specific kernel code +$(PKLIB): + $(MAKE) -I $(IMAGE_SRCDIR) -C $(PK_MAKE_DIR) + +#Build the code that is common for all processors (PPEs and 405) +#$(COMMONLIB): +# $(MAKE) -I $(IMAGE_SRCDIR) -C $(COMMONLIB_SRCDIR) + +ifdef P2P_ENABLE +$(P2PLIB): + $(MAKE) -I $(IMAGE_SRCDIR) -C $(P2P_SRCDIR) +endif + +# collect all of the trace hash files for this image into a single trexStringFile +.PHONY : tracehash +tracehash: + mkdir -p $(OBJDIR) + $(THASH) -c -d $(OBJDIR) -s $(OBJDIR)/trexStringFile + +#clean the kernel directory first, then the application level clean +clean: + rm -fr $(OBJDIR) + +#Add dependencies to header files +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/src/ppe/sbe/sample/img_defs.mk b/src/ppe/sbe/sample/img_defs.mk new file mode 100644 index 0000000..7211acb --- /dev/null +++ b/src/ppe/sbe/sample/img_defs.mk @@ -0,0 +1,265 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/sbe/sample/img_defs.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# Make header for GPE PK builds +# +# The application may define the following variables to control the +# build process: +# +# IMG_INCLUDES : Aplication-specific header search paths +# +# DEFS : A string of -D<symbol>[=<value>] to control compilation +# +# PK : Default ..; The path to the PK source code. +# The default is set for building the PK +# subdirectories. +# +# PK_THREAD_SUPPORT : (0/1, default 1); Compile PK thread and +# semaphore suppprt +# +# PK_TIMER_SUPPORT : (0/1, default 1); Compile PK timer suppprt +# +# SIMICS_ENVIRONMENT : (0/1, current default 0); Compile for Simics +# +# SIMICS_MAGIC_PANIC : (0/1, current default 0); Use Simics Magic +# breakpoint for PK_PANIC() instead of PowerPC trap. +# Note that Simics does not model trap correctly in +# external debug mode. +# +# GCC-O-LEVEL : The optimization level passed to GCC (default -Os). May +# also be defined empty (GCC-O-LEVEL=) to disable +# optimization. This variable can also be used to pass +# any other non-default setting to GCC, e.g. +# make GCC-O-LEVEL="-Os -fno-branch-count-reg" +# +# GCC-TOOL-PREFIX : The full path (including executable file prefixes) to +# the GCC cross-development tools to use. The default is +# "ppcnf-mcp5-" +# +# CTEPATH : This variable defaults to the afs/awd CTE tool +# installation - The PORE binutils are stored there. If +# you are not in Austin be sure to define CTEPATH in +# your .profile. +# +# OBJDIR : target directory for all generated files + +IMAGE_NAME := sample_ppe + +PPE_TYPE := ppe + +ifndef IMAGE_SRCDIR +export IMAGE_SRCDIR = $(abspath .) +endif + +ifndef IMG_INCLUDES +export IMG_INCLUDES = -I$(IMAGE_SRCDIR) +endif + +ifndef BASE_OBJDIR +export BASE_OBJDIR = $(abspath ../../../obj) +endif + +export IMG_OBJDIR = $(BASE_OBJDIR)/$(IMAGE_NAME) + +ifndef PK_SRCDIR +export PK_SRCDIR = $(abspath ../../pk) +endif + +ifndef GCC-TOOL-PREFIX +#GCC-TOOL-PREFIX = $(CTEPATH)/tools/ppcgcc/prod/bin/powerpc-linux- +GCC-TOOL-PREFIX = /afs/bb/u/rembold/openpower/op-build/output/host/usr/bin/powerpc64-linux- +#GCC-TOOL-PREFIX = /afs/bb/u/rembold/openpower/op-build/buildroot/output/host/usr/bin/powerpc-linux- +#GCC-TOOL-PREFIX = /afs/bb/u/rembold/openpower/op-build/output/host/usr/powerpc64-buildroot-linux-gnu/bin/ +#GCC-TOOL-PREFIX = /afs/bb/u/rembold/openpower/opcustom/op-build/buildroot/output/host/usr/bin/powerpc-linux- +endif + +ifndef BINUTILS-TOOL-PREFIX +BINUTILS-TOOL-PREFIX = $(CTEPATH)/tools/ppetools/prod/powerpc-eabi/bin/ +endif + +ifndef P2P_SRCDIR +export P2P_SRCDIR = $(abspath ../../tools/PowerPCtoPPE) +endif + +ifndef PPETRACEPP_DIR +export PPETRACEPP_DIR = $(abspath ../../tools/ppetracepp) +endif + +OBJDIR = $(BASE_OBJDIR)$(SUB_OBJDIR) + + +CC_ASM = $(GCC-TOOL-PREFIX)gcc +TCC = $(PPETRACEPP_DIR)/ppetracepp $(GCC-TOOL-PREFIX)gcc +CC = $(GCC-TOOL-PREFIX)gcc +AS = $(BINUTILS-TOOL-PREFIX)as +AR = $(BINUTILS-TOOL-PREFIX)ar +LD = $(BINUTILS-TOOL-PREFIX)ld +OBJDUMP = $(BINUTILS-TOOL-PREFIX)objdump +OBJCOPY = $(BINUTILS-TOOL-PREFIX)objcopy +TCPP = $(PPETRACEPP_DIR)/ppetracepp $(GCC-TOOL-PREFIX)gcc +THASH = $(PPETRACEPP_DIR)/tracehash.pl +CPP = $(GCC-TOOL-PREFIX)gcc + +ifdef P2P_ENABLE +PCP = $(P2P_SRCDIR)/ppc-ppe-pcp.py +endif + + +ifndef CTEPATH +$(warning The CTEPATH variable is not defined; Defaulting to /afs/awd) +export CTEPATH = /afs/awd/projects/cte +endif + +ifeq "$(PK_TIMER_SUPPORT)" "" +PK_TIMER_SUPPORT = 1 +endif + +ifeq "$(PK_THREAD_SUPPORT)" "" +PK_THREAD_SUPPORT = 1 +endif + +ifeq "$(PK_TRACE_SUPPORT)" "" +PK_TRACE_SUPPORT = 1 +endif + +# Generate a 16bit trace string hash prefix value based on the name of this image. This will form +# the upper 16 bits of the 32 bit trace hash values. +ifndef PK_TRACE_HASH_PREFIX +PK_TRACE_HASH_PREFIX := $(shell echo $(IMAGE_NAME) | md5sum | cut -c1-4 | xargs -i printf "%d" 0x{}) +endif + + +ifndef GCC-O-LEVEL +#GCC-O-LEVEL = -Os +GCC-O-LEVEL = -O -g +endif + +GCC-DEFS += -DIMAGE_NAME=$(IMAGE_NAME) +GCC-DEFS += -DPK_TIMER_SUPPORT=$(PK_TIMER_SUPPORT) +GCC-DEFS += -DPK_THREAD_SUPPORT=$(PK_THREAD_SUPPORT) +GCC-DEFS += -DPK_TRACE_SUPPORT=$(PK_TRACE_SUPPORT) +GCC-DEFS += -DPK_TRACE_HASH_PREFIX=$(PK_TRACE_HASH_PREFIX) +GCC-DEFS += -D__PK__=1 +DEFS += $(GCC-DEFS) + +############################################################################ + +INCLUDES += $(IMG_INCLUDES) \ + -I$(PK_SRCDIR)/kernel -I$(PK_SRCDIR)/ppe42 -I$(PK_SRCDIR)/trace \ + -I$(PK_SRCDIR)/$(PPE_TYPE) -I$(PK_SRCDIR)/../include \ + -I$(PK_SRCDIR)/../tools/ppetracepp + +PIPE-CFLAGS = -pipe -Wa,-m405 + +GCC-CFLAGS += -Wall -fsigned-char -msoft-float \ + -mcpu=405 -m32 -mmulhw -mmultiple \ + -meabi -msdata=eabi \ + -ffreestanding -fno-common -Werror \ + -fno-inline-functions-called-once \ + -ffixed-r11 -ffixed-r12 \ + -ffixed-r14 -ffixed-r15 -ffixed-r16 -ffixed-r17 \ + -ffixed-r18 -ffixed-r19 -ffixed-r20 -ffixed-r21 \ + -ffixed-r22 -ffixed-r23 -ffixed-r24 -ffixed-r25 \ + -ffixed-r26 -ffixed-r27 \ + -ffixed-cr1 -ffixed-cr2 -ffixed-cr3 -ffixed-cr4 \ + -ffixed-cr5 -ffixed-cr6 -ffixed-cr7 #-lstdc++ + + +CFLAGS = -c $(GCC-CFLAGS) $(PIPE-CFLAGS) $(GCC-O-LEVEL) $(INCLUDES) + +CPPFLAGS = -E + +ASFLAGS = -mppe42 + +ifdef P2P_ENABLE +#use this to disable optimizations (fused compare/branch etc.) +PCP-FLAG = + +#use this to enable optimizations +#PCP-FLAG = +endif +############################################################################ + +#override the GNU Make implicit rule for going from a .C to a .o +%.o: %.C + +$(OBJDIR)/%.s: %.C + $(TCC) $(CFLAGS) $(DEFS) -S -o $@ $< + + +#override the GNU Make implicit rule for going from a .c to a .o +%.o: %.c + +$(OBJDIR)/%.s: %.c + $(TCC) $(CFLAGS) $(DEFS) -S -o $@ $< + +#override the GNU Make implicit rule for going from a .S to a .o +%.o: %.S + +$(OBJDIR)/%.s: %.S + $(TCPP) $(CFLAGS) $(DEFS) $(CPPFLAGS) -o $@ $< +.PRECIOUS: $(OBJDIR)/%.s + +ifndef P2P_ENABLE + +$(OBJDIR)/%.o: $(OBJDIR)/%.s + $(AS) $(ASFLAGS) -o $@ $< + +else + +$(OBJDIR)/%.es: $(OBJDIR)/%.s + $(PCP) $(PCP-FLAG) -f $< +.PRECIOUS: $(OBJDIR)/%.es + +$(OBJDIR)/%.o: $(OBJDIR)/%.es + $(AS) $(ASFLAGS) -o $@ $< + +endif + +# From the GNU 'Make' manual - these scripts uses the preprocessor to +# create dependency files (*.d), then mungs them slightly to make them +# work as Make targets. The *.d files are include-ed in the +# subdirectory Makefiles. + +$(OBJDIR)/%.d: %.C + @set -e; rm -f $@; \ + echo -n "$(OBJDIR)/" > $@.$$$$; \ + $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) $(DEFS) $< >> $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +$(OBJDIR)/%.d: %.c + @set -e; rm -f $@; \ + echo -n "$(OBJDIR)/" > $@.$$$$; \ + $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) $(DEFS) $< >> $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +$(OBJDIR)/%.d: %.S + @set -e; rm -f $@; \ + echo -n "$(OBJDIR)/" > $@.$$$$; \ + $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) $(DEFS) $< >> $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + diff --git a/src/ppe/sbe/sample/link.cmd b/src/ppe/sbe/sample/link.cmd new file mode 100644 index 0000000..c3bff22 --- /dev/null +++ b/src/ppe/sbe/sample/link.cmd @@ -0,0 +1,92 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/sample/link.cmd $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ + +// Need to do this so that elf32-powerpc is not modified! +#undef powerpc + +#ifndef INITIAL_STACK_SIZE +#define INITIAL_STACK_SIZE 256 +#endif + +OUTPUT_FORMAT(elf32-powerpc); + +MEMORY +{ + sram : ORIGIN = 0xFFF40000, LENGTH = 0xc0000 +} + +SECTIONS +{ + . = 0xfff40000; + .text : {. = ALIGN(512); *(.vectors) *(.text)} > sram + + //////////////////////////////// + // Read-only Data + //////////////////////////////// + + . = ALIGN(8); + _RODATA_SECTION_BASE = .; + + // SDA2 constant sections .sdata2 and .sbss2 must be adjacent to each + // other. Our SDATA sections are small so we'll use strictly positive + // offsets. + + _SDA2_BASE_ = .; + .sdata2 . : { *(.sdata2) } > sram + .sbss2 . : { *(.sbss2) } > sram + + // Other read-only data. + + .rodata . : { *(.rodata*) *(.got2) } > sram + + _RODATA_SECTION_SIZE = . - _RODATA_SECTION_BASE; + + //////////////////////////////// + // Read-write Data + //////////////////////////////// + + . = ALIGN(8); + _DATA_SECTION_BASE = .; + + // SDA sections .sdata and .sbss must be adjacent to each + // other. Our SDATA sections are small so we'll use strictly positive + // offsets. + + _SDA_BASE_ = .; + .sdata . : { *(.sdata) } > sram + .sbss . : { *(.sbss) } > sram + + // Other read-write data + // It's not clear why boot.S is generating empty .glink,.iplt + + .rela . : { *(.rela*) } > sram + .rwdata . : { *(.data) *(.bss) } > sram +// .iplt . : { *(.iplt) } > sram + + _PK_INITIAL_STACK_LIMIT = .; + . = . + INITIAL_STACK_SIZE; + _PK_INITIAL_STACK = . - 1; + +} diff --git a/src/ppe/sbe/sample/pk_scom.c b/src/ppe/sbe/sample/pk_scom.c new file mode 100644 index 0000000..6b2c0b9 --- /dev/null +++ b/src/ppe/sbe/sample/pk_scom.c @@ -0,0 +1,236 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/sample/pk_scom.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_scom.c +/// \brief Lowest level SCOM definitions. +/// +/// A fapi-level SCOM should call these functions. +/// +/// Todo: +/// - Poll PCB master for SCOM completion. +/// - Return error code of SCOM fails. +/// - Return error code if SCOM input parms violate rules. + +#include "pk.h" +#include "pk_scom.h" + +uint32_t putscom( uint32_t i_chiplet_id, uint32_t i_address, uint64_t i_data) +{ + uint32_t l_cid=0; + + // CMO-Declaring variables tied to specific registers enables us to protect + // the SCOM data and address variables used in the new stvd and lvd 64-bit + // data instructions. This protection is needed since the new instructions + // are not yet properly considered by the compiler. + // l_dataH is used to represent the "beginning" of the 64-bit data in d8 + // (i.e., r8+r9). + uint32_t register l_dataH asm("r8")=0; + uint32_t register l_dataL asm("r9")=0; + uint32_t register l_addr_eff asm("r10")=0; + uint32_t register l_scratch asm("r31")=0; + + if (i_chiplet_id) + { + // Accommodate two different ways of supplying the chiplet ID: + // 0xNN000000: Only bits in high-order two nibbles : Valid + // 0x000000NN: Only bits in low-order two nibbles : Valid + // + if ((i_chiplet_id & 0xFF000000) == i_chiplet_id) + { + // Valid: Chiplet ID in high-order two nibbles. + l_cid = i_chiplet_id; + } + else if ((i_chiplet_id & 0x000000FF) == i_chiplet_id) + { + // Valid: Chiplet ID in low-order two nibbles. Convert to high-order. + l_cid = i_chiplet_id << 24; + } + else + { + // Invalid: Invalid type of chiplet ID + PK_TRACE("putscom() : Invalid value of i_chiplet_id (=0x%08X)",i_chiplet_id); + return 1; //CMO-improve Return sensible rc here. + } + + l_addr_eff = (i_address & 0x00FFFFFF) | l_cid; + } + else + { + // Chiplet ID is zero. Accept address as is. + // This is useful for PIB addresses and non-EX chiplets, and even for + // EX chiplets if the fully qualified EX chiplet addr is already known. + l_addr_eff = i_address; + + } + + l_dataH = (uint32_t)(i_data>>32); + l_dataL = (uint32_t)(i_data); + + // CMO-The following sequence forces usage of l_dataH/L and l_addr_eff + // and thus the population of them as well. + // Further note that unless l_dataH/L are placed right before the following + // sequence, more specifically, if they're placed at the top of putscom(), + // r8, or l_dataH, might be overwritten in the if(chiplet_id) section. + // Secondly, we test l_addr_eff for non-zero through the CR0 register + // (which was populated in the "mr." instruction.) This is to convince the + // compiler that we actually used l_addr_eff for something. + // At present the test result causes no action except to execute the stvd + // instruction in either case. + asm volatile ( \ + "mr. %0, %1 \n" \ + : "=r"(l_scratch) \ + : "r"(l_dataH) ); + asm volatile ( \ + "mr. %0, %1 \n" \ + : "=r"(l_scratch) \ + : "r"(l_dataL) ); + asm volatile ( \ + "mr. %0, %1 \n" \ + : "=r"(l_scratch) \ + : "r"(l_addr_eff) ); + asm volatile ( \ + "beq 0x4 \n" ); + + +/* asm volatile ( \ + "stw %[data], 0(%[effective_address]) \n" \ + : [data]"=r"(l_dataH) \ + : [effective_address]"r"(l_addr_eff) ); +*/ + // CMO-This instruction is not fully supported by the compiler (as of + // 20150108): + // - Correct: It is correctly translated into the proper OP code + // format. + // - Incorrect: The compiler does not seem to recognize the usage + // of the two l_xyz variables in that it doesn't + // know prior to this command that the registers that + // contain the values of l_xyz need to be protected + // up to this point. Thus, we are forced to use those + // two l_xyz variables in some dummy instructions just + // before this point in order to protect them. + asm volatile ( \ + "stvd %[data], 0(%[effective_address]) \n" \ + : [data]"=r"(l_dataH) \ + : [effective_address]"r"(l_addr_eff) ); + + // CMO-TBD + // Check PIB response code in 0x00001007(17:19) + // Translate PIB rc to PK rc + // Does this rc get reset to zero on success? + // Do we need to check this rc prior to issuing the SCOM? + + return 0; +} + + +uint32_t getscom( uint32_t i_chiplet_id, uint32_t i_address, uint64_t *o_data) +{ + uint32_t l_cid=0; + + // CMO-Declaring variables tied to specific registers enables us to protect + // the SCOM data and address variables used in the new stvd and lvd 64-bit + // data instructions. This protection is needed since the new instructions + // are not yet properly considered by the compiler. + // l_dataH is used to represent the "beginning" of the 64-bit data in d8 + // (i.e., r8+r9). + uint32_t register l_dataH asm("r8")=0; + uint32_t register l_dataL asm("r9")=0; + uint32_t register l_addr_eff asm("r10")=0; + uint32_t register l_scratch asm("r31")=0; + + if (i_chiplet_id) + { + // Accommodate two different ways of supplying the chiplet ID: + // 0xNN000000: Only bits in high-order two nibbles : Valid + // 0x000000NN: Only bits in low-order two nibbles : Valid + // + if ((i_chiplet_id & 0xFF000000) == i_chiplet_id) + { + // Valid: Chiplet ID in high-order two nibbles. + l_cid = i_chiplet_id; + } + else if ((i_chiplet_id & 0x000000FF) == i_chiplet_id) + { + // Valid: Chiplet ID in low-order two nibbles. Convert to high-order. + l_cid = i_chiplet_id << 24; + } + else + { + // Invalid: Invalid type of chiplet ID + PK_TRACE("getscom() : Invalid value of i_chiplet_id (=0x%08X)",i_chiplet_id); + return 1; //CMO-improve Return sensible rc here. + } + + l_addr_eff = (i_address & 0x00FFFFFF) | l_cid; + } + else + { + // Chiplet ID is zero. Accept address as is. + // This is useful for PIB addresses and non-EX chiplets, and even for + // EX chiplets if the fully qualified EX chiplet addr is already known. + l_addr_eff = i_address; + } + + // CMO-The following sequence forces usage of l_addr_eff and thus the + // population of it as well. + // Secondly, we test l_addr_eff for non-zero through the CR0 register + // (which was populated in the "mr." instruction.) This is to convince the + // compiler that we actually used l_addr_eff for something. + // At present the test result causes no action except to execute the lvd + // instruction in either case. + asm volatile ( \ + "mr. %0, %1 \n" \ + : "=r"(l_scratch) \ + : "r"(l_addr_eff) ); + asm volatile ( \ + "beq 0x4 \n" ); + + asm volatile ( \ + "lvd %[data], 0(%[effective_address]) \n" \ + : [data]"=r"(l_dataH) \ + : [effective_address]"r"(l_addr_eff) ); + + // CMO-The following sequence moves the read data, in l_dataH/L, into the + // 64-bit o_data location. + asm volatile ( \ + "stw %0, 0(%1) \n" \ + : "=r"(l_dataH) \ + : "r"(o_data) ); + asm volatile ( \ + "stw %0, 4(%1) \n" \ + : "=r"(l_dataL) \ + : "r"(o_data) ); + + // CMO-TBD + // Check PIB response code in 0x00001007(17:19) + // Translate PIB rc to PK rc + + return 0; +} diff --git a/src/ppe/sbe/sample/pk_scom.h b/src/ppe/sbe/sample/pk_scom.h new file mode 100644 index 0000000..f558abf --- /dev/null +++ b/src/ppe/sbe/sample/pk_scom.h @@ -0,0 +1,67 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/sample/pk_scom.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file sample_main.c +/// \brief Sample program that creates and starts a thread +/// +/// This file demonstrates how to create a thread and run it. It also provides +/// an example of how to add traces to the code. + +#ifndef __PK_SCOM_H__ +#define __PK_SCOM_H__ + +/// SCOM operations return non-zero error codes that may or may not indicate +/// an actual error, depending on which SCOM is begin accessed. This error +/// code is returned as the value of get/putscom(). The error code value +/// increases with teh severity of the error. +#define CFAM_FSI_STATUS_0x00001007 0x00001007 +typedef union cfam_fsi_status_reg { + uint64_t value; + struct { + uint64_t ignore_fields1 : 17 ; + uint64_t pib_error_code : 3 ; + uint64_t igore_fields2 : 44 ; + } fields; +} cfam_fsi_status_reg_t; + +#define PCB_ERROR_NONE 0 +#define PCB_ERROR_RESOURCE_OCCUPIED 1 +#define PCB_ERROR_CHIPLET_OFFLINE 2 +#define PCB_ERROR_PARTIAL_GOOD 3 +#define PCB_ERROR_ADDRESS_ERROR 4 +#define PCB_ERROR_CLOCK_ERROR 5 +#define PCB_ERROR_PACKET_ERROR 6 +#define PCB_ERROR_TIMEOUT 7 + +uint32_t putscom( uint32_t i_chiplet, uint32_t i_address, uint64_t i_data); + +uint32_t getscom( uint32_t i_chiplet, uint32_t i_address, uint64_t *o_data); + +#endif // __PK_SCOM_H__ diff --git a/src/ppe/sbe/sample/pk_trace_wrap.c b/src/ppe/sbe/sample/pk_trace_wrap.c new file mode 100644 index 0000000..4237b29 --- /dev/null +++ b/src/ppe/sbe/sample/pk_trace_wrap.c @@ -0,0 +1,33 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/sample/pk_trace_wrap.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#include "pk_trace_wrap.h" +#include "pk.h" +#include "pk_trace.h" + + +void pk_trace_wrap(const char* str) +{ + PK_TRACE("testsetest"); +} diff --git a/src/ppe/sbe/sample/pk_trace_wrap.h b/src/ppe/sbe/sample/pk_trace_wrap.h new file mode 100644 index 0000000..f3c8ac6 --- /dev/null +++ b/src/ppe/sbe/sample/pk_trace_wrap.h @@ -0,0 +1,31 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/sample/pk_trace_wrap.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef __PK_WRAP_WRAP_H__ +#define __PK_WRAP_WRAP__H__ + + +void pk_trace_wrap(const char*); + +#endif // __PK_WRAP_WRAP_H__ diff --git a/src/ppe/sbe/sample/sample_main.C b/src/ppe/sbe/sample/sample_main.C new file mode 100644 index 0000000..0d59138 --- /dev/null +++ b/src/ppe/sbe/sample/sample_main.C @@ -0,0 +1,123 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/sbe/sample/sample_main.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file sample_main.c +/// \brief Sample program that creates and starts a thread +/// +/// This file demonstrates how to create a thread and run it. It also provides +/// an example of how to add traces to the code. +extern "C" { +#include "pk.h" +#include "pk_trace.h" +#include "pk_scom.h" +#include "pk_trace_wrap.h" +} +#define KERNEL_STACK_SIZE 256 +#define MAIN_THREAD_STACK_SIZE 256 + + + +uint8_t G_kernel_stack[KERNEL_STACK_SIZE]; +uint8_t G_main_thread_stack[MAIN_THREAD_STACK_SIZE]; +PkThread G_main_thread; + +class Thetest { + + public: + int i; + +}; + +// A simple thread that just increments a local variable and sleeps +void main_thread(void* arg) +{ + //Thetest mytest; + + //mytest.i = 0; + + //std::cout << "sdfds" << std::endl; + + uint16_t a = 0; + + pk_trace_wrap("sdfsdf"); + //PK_TRACE("thread started"); + + + while(1) + { + // PK_TRACE can take up to 4 parameters + // (not including the format string) + //PK_TRACE("thread seconds = %d", a); + pk_sleep(PK_SECONDS(1)); + + uint64_t i_data = 0x0110; + + putscom(0x33333, 0x11111, i_data); + + getscom(0x33333, 0x11111, &i_data); + + a++; + } +} + + +// The main function is called by the boot code (after initializing some +// registers) +int main(int argc, char **argv) +{ + // initializes kernel data (stack, threads, timebase, timers, etc.) + pk_initialize((PkAddress)G_kernel_stack, + KERNEL_STACK_SIZE, + 0, + 500000000); + + //PK_TRACE("Kernel init completed"); + + //Initialize the thread control block for G_main_thread + pk_thread_create(&G_main_thread, + (PkThreadRoutine)main_thread, + (void*)NULL, + (PkAddress)G_main_thread_stack, + (size_t)MAIN_THREAD_STACK_SIZE, + (PkThreadPriority)1); + + //PK_TRACE_BIN("G_main_thread", &G_main_thread, sizeof(G_main_thread)); + + //Make G_main_thread runnable + pk_thread_resume(&G_main_thread); + + //PK_TRACE("Starting thread(s)"); + + // Start running the highest priority thread. + // This function never returns + pk_start_threads(); + + return 0; +} diff --git a/src/ppe/sbe/sample/topfiles.mk b/src/ppe/sbe/sample/topfiles.mk new file mode 100644 index 0000000..b3ee1e2 --- /dev/null +++ b/src/ppe/sbe/sample/topfiles.mk @@ -0,0 +1,30 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/sbe/sample/topfiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +TOP-C-SOURCES = pk_trace_wrap.c pk_scom.c +TOP-CPP-SOURCES = sample_main.C +TOP-S-SOURCES = + + +TOP_OBJECTS = $(TOP-C-SOURCES:.c=.o) $(TOP-CPP-SOURCES:.C=.o) $(TOP-S-SOURCES:.S=.o) diff --git a/src/ppe/tools/PowerPCtoPPE/Makefile b/src/ppe/tools/PowerPCtoPPE/Makefile new file mode 100644 index 0000000..421f98e --- /dev/null +++ b/src/ppe/tools/PowerPCtoPPE/Makefile @@ -0,0 +1,47 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/tools/PowerPCtoPPE/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 + +export SUB_OBJDIR = /p2p + +include img_defs.mk +include p2pfiles.mk + +OBJS := $(addprefix $(OBJDIR)/, $(P2P_OBJECTS)) + +libp2p.a: $(OBJS) + $(AR) crs $(OBJDIR)/libp2p.a $(OBJDIR)/*.o + +.PHONY: clean p2p +p2p: $(OBJS) + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif + diff --git a/src/ppe/tools/PowerPCtoPPE/p2p-test-gen.py b/src/ppe/tools/PowerPCtoPPE/p2p-test-gen.py new file mode 100755 index 0000000..c736600 --- /dev/null +++ b/src/ppe/tools/PowerPCtoPPE/p2p-test-gen.py @@ -0,0 +1,171 @@ +#!/usr/bin/python2.6 +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/tools/PowerPCtoPPE/p2p-test-gen.py $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 + +# \file p2p-test-gen.py +# \brief this program generates random constructed test cases +# in the form of input file consumed by ppc-ppe-pcp.py +# \usage create a file named 'test.s' and make sure it has at +# least one blank line before executing this program. + +import fileinput +import random + +DotLabel = ['', 'Label:', '.Label'] + +Comments = ['', '// Comments', '/* Comments */'] + +TabSpace = ['', '\t', ' ', '\t ', ' \t', ' \t '] + +RegLabel = ['', '%r'] + +Register = [0,1,2,3,4,5,6,7,8,9,10,13,28,29,30,31] + +TestEnable = [0,1,2,3] + +TestBook = {'eieio' : 0, + 'isync' : 0, + 'icbi' : 0, + 'icbt' : 0, + 'stbux' : 3, + 'sthux' : 3, + 'stwux' : 3, + 'lbzux' : 3, + 'lhzux' : 3, + 'lwzux' : 3, + 'lha' : 2, + 'lhau' : 2, + 'lhax' : 3, + 'lhaux' : 3, + 'mulhhw' : 3, + 'mulhhwu' : 3, + 'mulhw' : 3, + 'mulhwu' : 3, + 'mullw' : 3, + 'mulli' : 1, + 'divw' : 3, + 'divwu' : 3, + 'lmw' : 2, + 'stmw' : 2, + 'lwz' : 4, + 'stw' : 4, + 'cmplw' : 5, + 'cmpw' : 5, + 'cmpwi' : 5} + +BranchList = ['bc', 'bcl', 'blt', 'bltl', 'ble', 'blel', 'bgt', 'bgtl', 'bge', + 'bgel', 'beq', 'beql', 'bne', 'bnel'] + +def p2p_test(): + for line in fileinput.input('test.s', inplace=1): + print '// start generating test cases:', + for opcode,format in TestBook.iteritems(): + opcode += ' ' + if random.randint(1, 10) > 5: + print random.sample(TabSpace,1)[0] + random.sample(Comments,1)[0] +\ + random.sample(TabSpace,1)[0] + else: + print random.sample(TabSpace,1)[0] + random.sample(DotLabel,1)[0] +\ + random.sample(TabSpace,1)[0] + if format == 0 in TestEnable: + print random.sample(TabSpace,1)[0] + opcode +\ + random.sample(TabSpace,1)[0] + random.sample(Comments,1)[0] + if format == 3 in TestEnable: + regs = random.sample(Register, 3) + reg_field = random.sample(RegLabel,1)[0] + str(regs[0]) + ',' +\ + random.sample(TabSpace,1)[0] +\ + random.sample(RegLabel,1)[0] + str(regs[1]) + ',' +\ + random.sample(TabSpace,1)[0] +\ + random.sample(RegLabel,1)[0] + str(regs[2]) + print random.sample(TabSpace,1)[0] + opcode +\ + random.sample(TabSpace,1)[0] + reg_field +\ + random.sample(TabSpace,1)[0] + random.sample(Comments,1)[0] + if format == 1 in TestEnable: + regs = random.sample(Register, 2) + reg_field = random.sample(RegLabel,1)[0] + str(regs[0]) + ',' +\ + random.sample(TabSpace,1)[0] +\ + random.sample(RegLabel,1)[0] + str(regs[1]) + ',' +\ + random.sample(TabSpace,1)[0] +\ + str(random.randint(-128, 128)) + print random.sample(TabSpace,1)[0] + opcode +\ + random.sample(TabSpace,1)[0] + reg_field +\ + random.sample(TabSpace,1)[0] + random.sample(Comments,1)[0] + if format == 2 in TestEnable: + regs = random.sample(Register, 2) + reg_field = random.sample(RegLabel,1)[0] + str(regs[0]) + ',' +\ + random.sample(TabSpace,1)[0] +\ + str(random.randint(-128, 128)) +\ + '(' + random.sample(RegLabel,1)[0] + str(regs[1]) + ')' + print random.sample(TabSpace,1)[0] + opcode +\ + random.sample(TabSpace,1)[0] + reg_field +\ + random.sample(TabSpace,1)[0] + random.sample(Comments,1)[0] + if format == 4 in TestEnable: + for i in [1,2]: + regs = random.sample(Register, 2) + reg_field = random.sample(RegLabel,1)[0] + str(regs[0]) + ',' +\ + random.sample(TabSpace,1)[0] +\ + str(random.randint(-128, 128)) +\ + '(' + random.sample(RegLabel,1)[0] + str(regs[1]) + ')' + print random.sample(TabSpace,1)[0] + opcode +\ + random.sample(TabSpace,1)[0] + reg_field +\ + random.sample(TabSpace,1)[0] + random.sample(Comments,1)[0] + if format == 5 in TestEnable: + if 'i' in opcode: + regs = random.sample(Register, 1) + reg_field = random.sample(RegLabel,1)[0] + str(regs[0]) + ',' +\ + random.sample(TabSpace,1)[0] +\ + random.sample(RegLabel,1)[0] +\ + str(random.randint(-128, 128)) + else: + regs = random.sample(Register, 2) + reg_field = random.sample(RegLabel,1)[0] + str(regs[0]) + ',' +\ + random.sample(TabSpace,1)[0] +\ + random.sample(RegLabel,1)[0] + str(regs[1]) + print random.sample(TabSpace,1)[0] + opcode +\ + random.sample(TabSpace,1)[0] + reg_field +\ + random.sample(TabSpace,1)[0] + random.sample(Comments,1)[0] + branch = random.sample(BranchList, 1)[0] + ' ' + if 'bc' in branch: + reg_field = random.sample(TabSpace,1)[0] +\ + str(random.randint(0, 15)) + ',' +\ + random.sample(TabSpace,1)[0] +\ + str(random.randint(0, 7)) + ',' +\ + random.sample(TabSpace,1)[0] +\ + str(random.randint(-128, 128)) +\ + random.sample(TabSpace,1)[0] + else: + reg_field = random.sample(TabSpace,1)[0] +\ + str(random.randint(-128, 128)) +\ + random.sample(TabSpace,1)[0] + print random.sample(TabSpace,1)[0] + branch +\ + random.sample(TabSpace,1)[0] + reg_field +\ + random.sample(TabSpace,1)[0] + random.sample(Comments,1)[0] + fileinput.close() + +if __name__ == '__main__': + p2p_test() + + + diff --git a/src/ppe/tools/PowerPCtoPPE/p2pfiles.mk b/src/ppe/tools/PowerPCtoPPE/p2pfiles.mk new file mode 100644 index 0000000..0f64982 --- /dev/null +++ b/src/ppe/tools/PowerPCtoPPE/p2pfiles.mk @@ -0,0 +1,38 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/tools/PowerPCtoPPE/p2pfiles.mk $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# @file p2pfiles.mk +# +# @brief mk for including P2P support library object files +# + +########################################################################## +# Object Files +########################################################################## +P2P-S-SOURCES = ppe42_mulhw.S ppe42_mulhwu.S ppe42_mullw.S \ + ppe42_divw.S ppe42_divwu.S + +P2P_OBJECTS = $(P2P-S-SOURCES:.S=.o) + + diff --git a/src/ppe/tools/PowerPCtoPPE/ppc-ppe-pcp.py b/src/ppe/tools/PowerPCtoPPE/ppc-ppe-pcp.py new file mode 100755 index 0000000..1d6635f --- /dev/null +++ b/src/ppe/tools/PowerPCtoPPE/ppc-ppe-pcp.py @@ -0,0 +1,1007 @@ +#!/usr/bin/python2.6 +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/tools/PowerPCtoPPE/ppc-ppe-pcp.py $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 + +# \file ppc-ppe-pcp.py +# \brief PPC405 Assembly to PPE42 Assembly Post-Compiler Processor (P2P) +# +# --------------------------------------------------------------- +# Revision History +# --------------------------------------------------------------- +# 10-07-2014: project completed +# daviddu added optimization profile support +# +# 10-06-2014: added fused compare and branch supprot +# daviddu added support for combining two ld/st into one double word +# added support to insert branch upon .p2align directive +# +# 09-27-2014: added subroutine support for mul* and div* +# daviddu added virtual double word replacing multiple word support +# +# 09-13-2014: initial version +# daviddu only instruction inline replacement is supported +# --------------------------------------------------------------- + +P2P_VERSION = "10-07-2014" # version number as last modified date +P2P_PPC_EXT = '.s' # PPC Assembly filename extension +P2P_PPE_EXT = '.es' # PPE Assembly filename extension +P2P_PPE_PRE = '__ppe42_' # PPE Assembly subroutine prefix + +import sys +import os +import re +import fnmatch +import fileinput + +# --------------------------------------------------------------- +# PPC405 Assembly to PPE42 Assembly Post-Compiler Processor (P2P) +# --------------------------------------------------------------- +# +# Description: +# +# This post-compiler processor will take PPC405 assembly file(s) produced +# by powerpc-linux-gcc or hand coded and replace some of the instructions +# supported by PPC405 ISA but not PPE42 ISA with a set of instructions +# supported by PPE42 ISA. Outcome of this program is PPE42 assembly file(s). +# +# Assumptions: +# +# - Input/Output File Name Extension: +# +# PPC405 assembly file generated by powerpc-linux-gcc has filename extension +# defined by "P2P_PPC_EXT" global variable, while PPE42 assembly file +# consumed by PPE Assembler has filename extension defined by "P2P_PPE_EXT" +# global variable. Both should be consistant with Makefile rules. +# +# - Registers: +# +# Instructions in input file should only use registers supported by PPE, +# that is R0-R10,R13,R28-R31 for GPRs and PPE only SPRs(for example, PPE +# only has CR0 instead of CR0-7). +# +# GCC flag -ffixed can be used to enforce compiler to not use certain +# registers if compiler generates input files to this script. Note certian +# optimization level, such as -Os, of GGC will still use certain registers +# regardless if -ffixed flag is used. Furthermore, compiler should not +# generate multiple word instructions(lmw/stmw) that covers the registers +# forbidden to use by -ffixed flag. +# +# Example of using -ffixed flag in this case: +# -ffixed-r11 -ffixed-r12 -ffixed-r14 -ffixed-r15 \ +# -ffixed-r16 -ffixed-r17 -ffixed-r18 -ffixed-r19 \ +# -ffixed-r20 -ffixed-r21 -ffixed-r22 -ffixed-r23 \ +# -ffixed-r24 -ffixed-r25 -ffixed-r26 -ffixed-r27 \ +# -ffixed-cr1 -ffixed-cr2 -ffixed-cr3 -ffixed-cr4 \ +# -ffixed-cr5 -ffixed-cr6 -ffixed-cr7 +# +# - Instructions: +# +# Instructions in input file should only use PowerPC 405 instructions +# covered by "PowerPC 405-S Embedded Processor Core" manual; however, +# there is an assumption on certain catalog of instructions will never be +# generated by power-linux-gcc compiler(or disabled by compiler switch). +# +# Also, compiler should generate extended mnemonics instead of its base +# instruction when extended mnemonics fits. +# +# Via -falign-labels=n and -O2 or -O3, the compiler inserts .p2align +# directive to help instruction alignment for best cache performance. +# +# - Assembly Syntax: +# +# There should be only white spaces before instruction mnemonics, in +# another word, all inline comments should be put behind the instrution. +# +# "Label:" and an instruction should not be on the same line, hand coded +# assembly should be consistant to this same compiler output format. +# +# Depandences: +# +# In order to utilize assembly subroutines implemented for supporting +# missing instructions of multiplication and division in PPE42 ISA, a given +# library(with assembly files and header) must be compiled and linked with +# any source code that use this program to generate PPE binary. +# +# Usage: +# +# ./<ThisScript> -f <a filename with path> --- process single file +# ./<ThisScript> -d <a directory path> --- process multiple files +# ./<ThisScript> -h --- detailed usage on other flags +# ./<ThisScript> -v --- version of the program +# ./<ThisScript> -d <a directory path> -s --- perform result profiling +# +# Functions: +# +# p2p_main - main function, parse options and arguments +# p2p_onefile - processing single PPC Assembly File +# p2p_combine - processing two PPC instructions in input file +# p2p_replace - processing single PPC instruction in input file +# +# Data Structures: +# +# ReplaceRules = { ppc_op : [rule, ppe_op] } +# CombineRules = { ppc_op : [rule, ppe_op] } +# FuseBranches = [ list of branches qualified for fusing with compares ] +# +#------------------------------------------------------------------------------ +# ReplaceRules: [ 'r', 'u', 'a', 'h', 's', 'o', 'd', 'm' ] +#-------|-------------------------|-------------------------------------------- +# Rule | Example (PPC to PPE) | Description +#-------|-------------------------|-------------------------------------------- +# 'r' | [ppc] ppc_op RT, RA, RB | simply 'replace' ppc opcode with ppe opcode +# 0 0 | [ppe] ppe_op RT, RA, RB | while the operands, if any, stay the same +#-------|-------------------------|-------------------------------------------- +# 'ru' | [ppc] ppc_op RT, RA, RB | on top of 'r' rule, emulate 'update' by +# | [ppe] ppe_op RT, RA, RB | appending "add" instruction after the +# +1 +1 | add RA, RA, RB | original instruction to update RA +#-------|-------------------------|-------------------------------------------- +# 'ra' | [ppc] ppc_op RT, D(RA) | on top of 'r' rule, emulate 'algebraic' by +# | [ppe] ppe_op RT, D(RA) | appending "extsh" instruction after the +# +1 +1 | extsh RT, RT | original instruction to sign-extend RT +#-------|-------------------------|-------------------------------------------- +# 'rau' | [ppc] ppc_op RT, RA, RB | combining rule 'r', 'a', and 'u' above. +# | [ppe] ppe_op RT, RA, RB | Note: there is no requirement on whether +# | add RA, RA, RB | rule 'a' or rule 'u' should be applied +# +2 +2 | extsh RT, RT | first, the outcome should be the same. +#-------|-------------------------|-------------------------------------------- +# 'h' | [ppc] ppc_op RT, RA, RB | rule of 'halfword' multiplication +# | [ppe] srwi RA, 16 | emulate multiply "high halfword" with +# | srwi RB, 16 | multiply "low halfword" by shifting +# +2 +2 | ppe_op RT, RA, RB | the operands first +#-------|-------------------------|-------------------------------------------- +# 's' | [ppc] ppc_op RT, RA, RB | emulate word multiply and divide +# | [ppe] stwu R1, -24(R1)| instructions with calling 'subroutines' +# | stvd D3, 8(R1) | implemented in ppe42_mul.S and ppe42_div.S +# | mflr R3 | +# | stw R3, 16(R1) | Calling Conventions:(SS = Stack Size) +# | mr R3, RA | +# | mr R4, RB | Caller is responsible for +# | bl target | 1) create stack frame +# | mr RT, R3 | 2) save off R3 and R4 to stack +# | lwz R3, 16(R1) | 3) save off link register to stack +# | mtlr R3 | 4) put operands into R3, R4 before branch +# | lvd D3, 8(R1) | 5) put result in R3 to RT after branch +# | lwz R1, 0(R1) | 6) restore link register from stack +# | | 7) restore R3 and R4 from stack +# | [sub] stwu R1, -SS(R1) | 8) remove the stack frame +# | <save volatile> | +# | (subroutine body) | Callee is responsible for +# | <restore volatile>| 1) create and remove stack frame +# | lwz R1, 0(R1) | 2) save and restore volatile registers +# +X +Y | blr | 3) subroutine will not touch LR again +#-------|-------------------------|-------------------------------------------- +# 'o' | [ppc] ppc_op[o] RT ... | rule of 'o' form for overflow +# | [ppe] ppe_op RT ... | Note: "mullwo", "divwo" and "divwuo" each +# | <inst specific> | has unique setting for XER[OV,SO] if OE = 1 +#-------|-------------------------|-------------------------------------------- +# 'd' | [ppc] ppc_op[.] RT ... | rule of '.' or 'dot' form for recording +# | [ppe] ppe_op RT ... | using "cmpwli" to emulate the [.] form +# | cmpwli RT, 0 | to the instruction result and CR0 fields +#-------|-------------------------|-------------------------------------------- +# 'm' | [ppc] ppc_op RT, D(RA) | emulate PowerPC load/store multiple word +# | [ppe] ppe_op DT, D(RA) | instructions with PPE specific +# | (doubleword ld/st)| 'virtual doubleword' instructions if target +# | or | address is 8-byte aligned; otherwise, using +# | (singleword ld/st)| single word instructions instead or mix both +# | or | Note only RA == R1/R2/R13 will always meet +# -1 -1 | (single & double) | alignment requirement of virtual doubleword +#-------|-------------------------|-------------------------------------------- +# +ReplaceRules = {#ppc_op : [ rule | ppe_op ] + #---------------------------- + #synchronization instructions + 'eieio' : [ 'r', 'sync' ], + 'isync' : [ 'r', 'nop' ], + 'icbi' : [ 'r', 'nop' ], + 'icbt' : [ 'r', 'nop' ], + 'mtcr' : [ 'r', 'mtcr0'], + #load/store with [u/x/a] form + 'stbux' : [ 'ru', 'stbx' ], + 'sthux' : [ 'ru', 'sthx' ], + 'stwux' : [ 'ru', 'stwx' ], + 'lbzux' : [ 'ru', 'lbzx' ], + 'lhzux' : [ 'ru', 'lhzx' ], + 'lwzux' : [ 'ru', 'lwzx' ], + 'lha' : [ 'ra', 'lhz' ], + 'lhau' : [ 'ra', 'lhzu' ], + 'lhax' : [ 'ra', 'lhzx' ], + 'lhaux' : [ 'rau', 'lhzx' ], + #multiply/divide with [./o] form + 'mulhhw' : [ 'h', 'mullhw' ], + 'mulhhw.' : [ 'h', 'mullhw.' ], + 'mulhhwu' : [ 'h', 'mullhwu' ], + 'mulhhwu.': [ 'h', 'mullhwu.' ], + 'mulhw' : [ 's', 'mulhw' ], + 'mulhw.' : [ 'sd', 'mulhw' ], + 'mulhwu' : [ 's', 'mulhwu' ], + 'mulhwu.' : [ 'sd', 'mulhwu' ], + 'mullw' : [ 's', 'mullw' ], + 'mullw.' : [ 'sd', 'mullw' ], + 'mullwo' : [ 'so', 'mullw' ], + 'mullwo.' : [ 'sod', 'mullw' ], + 'mulli' : [ 's', 'mullw' ], + 'divw' : [ 's', 'divw' ], + 'divw.' : [ 'sd', 'divw' ], + 'divwo' : [ 'so', 'divw' ], + 'divwo.' : [ 'sod', 'divw' ], + 'divwu' : [ 's', 'divwu' ], + 'divwu.' : [ 'sd', 'divwu' ], + 'divwuo' : [ 'so', 'divwu' ], + 'divwuo.' : [ 'sod', 'divwu' ], + #load/store multiple word(Rx-R31) + 'lmw' : [ 'm', 'lvd,lwz' ], + 'stmw' : [ 'm', 'stvd,stw' ]} + + +#------------------------------------------------------------------------------ +# CombineRules: [ 'f', 'v', 'l' ] +#-------|-------------------------|-------------------------------------------- +# 'f' | [ppc] ppc_op(cmp*) | rule for 'fusing' adjacent pair of compare +# | ppc_op(b*) | and branch(PPE specific). Note: only +# -1 0 | [ppe] ppe_op(cmp*b*) | extended mnemonics of compares are handled +#-------|-------------------------|-------------------------------------------- +# 'v' | [ppc] ppc_op(lwz/stw) | rule for combining double word aligned +# | ppc_op(lwz/stw) | load/store pairs into signle 'virtual' +# -1 -1 | [ppe] ppe_op(lvd/stvd) | double word instructions(PPE specific) +#-------|-------------------------|-------------------------------------------- +# 'l' | [ppc] .p2align | compiler will insert ".p2align" directive to +# | Label: | help instructions align from label to label. +# | [ppe] b Label | then assembler will insert "nop" on .p2align +# | .p2align | directive. a "branch" to skip the nops will +# 0 -1 | Label: | improve the performance while still aligned +#-------|-------------------------|-------------------------------------------- +# +CombineRules = {#ppc_op : [ rule | ppe_cp ] + #-------------------------- + #8byte aligned loads/stores + 'lwz' : [ 'v', 'lvd' ], + 'stw' : [ 'v', 'stvd' ], + #compares fusable to branch + 'cmplw' : [ 'f', 'cmplw' ], + 'cmpw' : [ 'f', 'cmpw' ], + 'cmpwi' : [ 'f', 'cmpwi' ], + #'.p2align' before 'label:' + '.p2align' : [ 'l', 'b' ]} + + +#------------------------------------------------------------------------------ +# FuseBranches: [ Branches can be fused into cmp*b* ] +#------------------------------------------------------------------------------ +# +FuseBranches = ['bc', 'bcl', + 'blt', 'bltl', 'ble', 'blel', + 'bgt', 'bgtl', 'bge', 'bgel', + 'beq', 'beql', 'bne', 'bnel'] + + +# ----------------------------------------------------------------------------- +# p2p_replace: +# process each line(filtered) in the assembly file to replace PPC instruction +# to supported PPE instruction(s) +# +# Arguments: +# string: line - assembly file line to be replaced +# ppc_op - detected PPC opcode that needs to be replaced +# Return: +# boolean: True - Return without Error +# False - Error Detected +# Variables: +# string: inst, rule, ppe_op, newline, temp_op +# double_inst, single_inst, virtual_reg, base_offset, address_reg +# Subroutine: +# NONE +# ----------------------------------------------------------------------------- +def p2p_replace(line, ppc_op): + + # parse PPC instruction as in I or D form with opcode and upto 3 operands: + # possible forms: opcode + # opcode RT, RA, RB + # opcode RT, RA, IM + # opcode RT, D(RA) + # inst.group(0) : <whole instruction> + # inst.group(1) : " " + # inst.group(2) : Opcode(.) + # inst.group(3) : " " + # inst.group(4) : GPR + # inst.group(5) : " , " + # inst.group(6) : GPR or Immediate(D) + # inst.group(7) : " , " or " ( " + # inst.group(8) : GPR or Immediate(IM) + # inst.group(9) : " ) " + inst = re.search(r"([\s]*)([a-zA-Z\.]+)([\s]*)([%r0-9]*)([\s,]*)([%r0-9\-]*)([\s,\(]*)([%r0-9\-]*)([\s\)]*)", line) + + # detect an error + if inst is None or ppc_op != inst.group(2): + return False + + # look up rule to process the instruction + rule, ppe_op = ReplaceRules[ppc_op] + + # if enabled, put a mark in the output file + if P2P_COMMENT: print "#P2P(%s):" % rule + line, + + # start cases of replacing PPC instruction with PPE instruction(s) + #---r------------------------------------------------------------------------ + if 'r' in rule: + + # replace opcode under rule 'r' and rewrite the instruction + newline = line.replace(ppc_op, ppe_op) + print newline, + + # do not continue if there is 'a' or 'u' rule to process on this line + if 'u' not in rule and 'a' not in rule: + return True + + #---u------------------------------------------------------------------------ + if 'u' in rule: + + # construct and write "add RA, RA, RB" under rule 'u' + newline = inst.group(1) + 'add' + inst.group(3) + inst.group(6) +\ + inst.group(5) + inst.group(6) + inst.group(7) + inst.group(8) + print newline + + # do not continue if there is 'a' rule to process on this line + if 'a' not in rule: + return True + + #---a------------------------------------------------------------------------ + if 'a' in rule: + + # construct and write "extsh RT, RT" under rule 'a' + newline = inst.group(1) + 'extsh' + inst.group(3) + inst.group(4) +\ + inst.group(5) + inst.group(4) + print newline + return True + + #---h------------------------------------------------------------------------ + if 'h' in rule: + + # construct and write "srwi RA, 16" under rule 'h' + newline = inst.group(1) + 'srwi' + inst.group(3) + inst.group(6) +\ + inst.group(5) + "16" + print newline + + # construct and write "srwi RB, 16" under rule 'h' + newline = inst.group(1) + 'srwi' + inst.group(3) + inst.group(8) +\ + inst.group(5) + "16" + print newline + + # replace opcode in original instruction and write under rule 'h' + newline = line.replace(ppc_op, ppe_op) + print newline + return True + + #---s------------------------------------------------------------------------ + if 's' in rule: + + # construct branch target label + ppe_op = P2P_PPE_PRE + ppe_op + + # construct and write "stwu R1, -24(R1)" to create the stack frame + newline = inst.group(1) + 'stwu' + inst.group(3) + '1' +\ + inst.group(5) + '-24(1)' + print newline + + # construct and write "stvd D3, 8(R1)" to save off R3 and R4 + newline = inst.group(1) + 'stvd' + inst.group(3) + '3' +\ + inst.group(5) + '8(1)' + print newline + + # construct and write "mflr R3" to fetch the current link address + newline = inst.group(1) + 'mflr' + inst.group(3) + '3' + print newline + + # construct and write "stw R3, 16(R1)" to save off current LR to stack + newline = inst.group(1) + 'stw' + inst.group(3) + '3' +\ + inst.group(5) + '16(1)' + print newline + + # construct and write "mr R3, RA" to copy the operand RA to R3 + newline = inst.group(1) + 'mr' + inst.group(3) + '3' +\ + inst.group(5) + inst.group(6) + print newline + + # if 'mulli' is detected, using 'li' instead of 'mr' for second operand + if ppc_op == 'mulli': + temp_op = 'li' + else: + temp_op = 'mr' + + # construct and write "mr R4, RB" to copy the operand RB to R4 + # or in 'mulli' case, "li R4, IM" to copy the operand IM to R4 + newline = inst.group(1) + temp_op + inst.group(3) + '4' +\ + inst.group(5) + inst.group(8) + print newline + + # using branch and link(bl) to branch to subroutine + # later subroutine can branch back using branch link register(blr) + # Assumption: the subroutine will be responsible for saving + # and restoring all the volatilo registers used in the subroutine + newline = inst.group(1) + 'bl' + inst.group(3) + ppe_op + print newline + + # construct and write "mr RT, R3" to copy the result in R3 to RT + newline = inst.group(1) + 'mr' + inst.group(3) + inst.group(4) +\ + inst.group(5) + '3' + print newline + + # construct and write "lwz R3, 16(R1)" to fetch the LR value from stack + newline = inst.group(1) + 'lwz' + inst.group(3) + '3' +\ + inst.group(5) + '16(1)' + print newline + + # construct and write "mtlr R3" to restore the link register + newline = inst.group(1) + 'mtlr' + inst.group(3) + '3' + print newline + + # construct and write "lvd D3, 8(R1)" to restore R3 and R4 + newline = inst.group(1) + 'lvd' + inst.group(3) + '3' +\ + inst.group(5) + '8(1)' + print newline + + # construct and write "lwz R1, 0(R1)" to destroy the stack frame + newline = inst.group(1) + 'lwz' + inst.group(3) + '1' +\ + inst.group(5) + '0(1)' + print newline + return True + + #---m------------------------------------------------------------------------ + if 'm' in rule: + + # parse instruction information + # note register can be in either "N" form or "%rN" form + double_inst,single_inst = ppe_op.split(',') + virtual_reg = int(re.search(r'\d+', inst.group(4)).group()) + base_offset = int(inst.group(6)) + address_reg = int(re.search(r'\d+', inst.group(8)).group()) + + # consider illegal if multiple word instruction covers non-exist registers + if virtual_reg < 28: + return False + + # loop until and include GPR31 + while virtual_reg < 32: + # page 270 of 405 manual, only do this for load instructions + if virtual_reg == address_reg != 31 and 'l' in single_inst: + base_offset += 4 + virtual_reg += 1 + continue + + # if other GPRs being address_reg there is no guarantee for alignment + if address_reg not in [1,2,13]: + # construct and write "lwz/stw RT, D(RA)" for every registers + newline = inst.group(1) + single_inst + inst.group(3) +\ + str(virtual_reg) + inst.group(5) + str(base_offset) +\ + inst.group(7) + inst.group(8) + inst.group(9) + print newline + base_offset += 4 + virtual_reg += 1 + else: + # if base_offset is also aligned with base address in the address_reg + # & there are at least two more registers to perform doubleword ld/st + if not (base_offset % 8) and (virtual_reg + 1) < 32: + # construct and write "lvd/stvd DR, D(RA)" under rule 'v' + newline = inst.group(1) + double_inst + inst.group(3) +\ + str(virtual_reg) + inst.group(5) + str(base_offset) +\ + inst.group(7) + inst.group(8) + inst.group(9) + print newline + base_offset += 8 + virtual_reg += 2 + # either only one register left or base_offset isnt aligned + else: + # construct and write "lwz/stwz SR, D(RA)" under rule 'v' + newline = inst.group(1) + single_inst + inst.group(3) +\ + str(virtual_reg) + inst.group(5) + str(base_offset) +\ + inst.group(7) + inst.group(8) + inst.group(9) + print newline + base_offset += 4 + virtual_reg += 1 + # end of this if-else + # end of while loop + return True + # end of last if + + +# ----------------------------------------------------------------------------- +# p2p_combine: +# process each two lines(filtered) in the assembly file to combine two PPC +# instructions to one PPE specific instruction for better performance +# +# Arguments: +# string: first_line - 1st assembly file line to be combined +# second_line - 2nd assembly file line to be combined +# first_op - 1st detected PPC opcode that needs to be combined +# second_op - 2nd detected PPC opcode that needs to be combined +# Return: +# boolean: done - True: return without error +# - False: return with error detected +# match - True: eventually matched and combined +# - False: fail to qualify to be combined +# Variables: +# string: first_inst, second_inst, rule, ppe_op, newline +# bo, px_bix, compare_operands, target +# Subroutine: +# NONE +# ----------------------------------------------------------------------------- +def p2p_combine(first_line, second_line, first_op, second_op): + + global P2P_SPACE; global P2P_CYCLE + global P2P_COMPARE_BRANCH; global P2P_VIRTUAL_DOUBLE + + # parse PPC instruction as in I or B or D form with opcode and upto 3 operands + # possible form : [1st] opcode [CR,] RA, RB + # [1st] opcode [CR,] RA, IM + # [1st] opcode RT, D(RA) + # [2nd] opcode [CR,] Target + # [2nd] opcode BO, BI, Target + # [2nd] opcode RT, D(RA) + # inst.group(0) : <whole instruction> + # inst.group(1) : " " + # inst.group(2) : Opcode(+/-/.) + # inst.group(3) : " " + # inst.group(4) : GPR or CR or BO or Target + # inst.group(5) : " , " + # inst.group(6) : GPR or IM or D(label+offset@sda21) or BI or Target + # inst.group(7) : " , " or " ( " + # inst.group(8) : GPR or IM or Target + # inst.group(9) : " ) " + first_inst = re.search(r"([\s]*)([a-zA-Z\+\-\.]+)([\s]*)([%a-zA-Z0-9_\.]*)([\s,]*)([%a-zA-Z0-9_@\.\-\+]*)([\s,\(]*)([%a-zA-Z0-9_\.\-]*)([\)]*)", first_line) + second_inst = re.search(r"([\s]*)([a-zA-Z\+\-\.]+)([\s]*)([%a-zA-Z0-9_\.]*)([\s,]*)([%a-zA-Z0-9_@\.\-\+]*)([\s,\(]*)([%a-zA-Z0-9_\.\-]*)([\)]*)", second_line) + + # detect an error + if first_inst is None or second_inst is None or \ + first_op != first_inst.group(2) or second_op not in second_inst.group(2): + return False,False + + # look up rule to process the instruction + rule, ppe_op = CombineRules[first_op] + + # start cases of combining two PPC instructions into PPE instruction + #---f------------------------------------------------------------------------ + if 'f' in rule: + + if not P2P_COMPARE_BRANCH: + return True,False + + # fusing compare and branch + ppe_op = ppe_op + second_op + + # for cmpwib* case, there is a difference between + # cmpwi SI operand as signed 16-bit integer and then got sign extended and + # cmpwib* UIX operand as unsigned 5-bit integer and then got zero extended + # thus, will not fuse the two if the integer operand is not in range(0,31) + # if cr field is omitted: + if ',' in first_inst.group(7): + # cr field must be cr0 or 0, error out if it is something else: + if '0' not in first_inst.group(4): + return False, True + if 'i' in first_op and (int(first_inst.group(8)) < 0 or \ + int(first_inst.group(8)) > 31): + return True,False + else: + compare_operands = first_inst.group(6) + first_inst.group(7) + \ + first_inst.group(8) + ', ' + else: + if 'i' in first_op and (int(first_inst.group(6)) < 0 or \ + int(first_inst.group(6)) > 31): + return True,False + else: + compare_operands = first_inst.group(4) + first_inst.group(5) + \ + first_inst.group(6) + ', ' + + # if 'bc' then extract BO,BI fields and convert to PX,BIX fields of 'cmp*b*' + # Note CTR decreament and branch always cases are not handled, and + # python bin() outputs "0bXXXXX" form so bo[2] is actually BO bit 0 + # else there is no need for PX,BIX fields for extended mnemonics + if 'bc' in second_op: + bo = bin(int(second_inst.group(4))) + + # do not handle CRT decreament or branch always cases + if bo[4] == 0 or bo[2] == 1: + return True,False + + # PX = BO bit 1, BIX = BI = [0,1,2,3] due to only CR0 is used + px_bix = bo[3] + second_inst.group(5) + \ + second_inst.group(6) + second_inst.group(7) + target = second_inst.group(8) + else: + px_bix = "" + # if cr field is omitted: + if ',' in second_inst.group(5): + # cr field must be cr0 or 0, error out if it is something else: + if '0' not in second_inst.group(4): + return False, True + target = second_inst.group(6) + else: + target = second_inst.group(4) + + # profile: space--, cycle is the same because 1+2==3 + P2P_SPACE -= 1 + + # if enabled, put a mark in the output file + if P2P_COMMENT: + print "#P2P(%s):" % rule + first_line, + print "#P2P(%s):" % rule + second_line, + + # construct and write "cmp*b* [PX,BIX,] RA,RB/IM,target" under 'f' rule + newline = first_inst.group(1) + ppe_op + first_inst.group(3) +\ + px_bix + compare_operands + target + print newline + return True,True + + + #---v------------------------------------------------------------------------ + if 'v' in rule: + + if not P2P_VIRTUAL_DOUBLE: + return True,False + + global P2P_VDW_SDA + + # Combinable Conditions: + # 1) base address registers must be the same and one of R1/R2/R13 + # 2) address offsets have to be 8-bytes continuous and aligned + # 3) target or source registers must qualify to be double word register + # Note: label+offset@sda21 format is coverted to target r13 after link + # assume data go in and out r13 or SDA space is always 8-byte aligned + # here we only check the continous of address offset and register pair + if first_inst.group(8) == second_inst.group(8) in ['1','2','13'] or \ + ("@sda21" in first_inst.group(6) and \ + "@sda21" in second_inst.group(6) and \ + P2P_VDW_SDA): + + if ((first_inst.group(6).replace("@sda21","") + "+4" == \ + second_inst.group(6).replace("@sda21","") and P2P_VDW_SDA) or \ + ((first_inst.group(6).isdigit() and \ + not int(first_inst.group(6)) % 8) and \ + int(first_inst.group(6)) + 4 == int(second_inst.group(6)))) and \ + (int(first_inst.group(4)) + 1 == int(second_inst.group(4)) or \ + (int(first_inst.group(4)) == 31 and \ + int(second_inst.group(4)) == 0)): + newline = first_line.replace(first_op, ppe_op) + elif ((second_inst.group(6).replace("@sda21","") + "+4" == \ + first_inst.group(6).replace("@sda21","") and P2P_VDW_SDA) or \ + ((second_inst.group(6).isdigit() and \ + not int(second_inst.group(6)) % 8) and \ + int(second_inst.group(6)) + 4 == int(first_inst.group(6)))) and \ + (int(second_inst.group(4)) + 1 == int(first_inst.group(4)) or \ + (int(second_inst.group(4)) == 31 and \ + int(first_inst.group(4)) == 0)): + newline = second_line.replace(second_op, ppe_op) + else: + return True,False + + # profile: space--, cycle--(same delay but 1 less from issue) + P2P_SPACE -= 1; P2P_CYCLE -= 1 + + # if enabled, put a mark in the output file + if P2P_COMMENT: + print "#P2P(%s):" % rule + first_line, + print "#P2P(%s):" % rule + second_line, + + print newline, + return True,True + else: + return True,False + + +# ----------------------------------------------------------------------------- +# p2p_onefile: +# process single PPC assembly file to convert it into PPE assembly file +# also filter out non-instruction lines before calling the subroutine +# +# Arguments: +# string: ppcFileName +# Return: +# boolean: done - True if file processing completed without error +# - False if file processing failed due to an error +# Variables: +# boolean: match, done +# string: ppeFileName, line, ppc_op, pre_op, pre_line, section, label +# integer: line_num, first_label_ln, second_label_ln, misalign +# Subroutine: +# p2p_combine +# p2p_replace +# ----------------------------------------------------------------------------- +def p2p_onefile(ppcFileName): + + global P2P_SPACE; P2P_SPACE = 0 # profile count + global P2P_CYCLE; P2P_CYCLE = 0 # profile count + + if P2P_VERBOSE : print "Translate PPC assembly: " + ppcFileName + + # new PPE assembly file is renamed as <filename>.s + ppeFileName = ppcFileName.replace(P2P_PPC_EXT, P2P_PPE_EXT) + os.rename(ppcFileName, ppeFileName) + + # initialize storage variables for previous line that needs to be remembered + pre_line = "" + pre_op = "" + + # use inline file editing, back up original PPC assembly file as <filename>.S + for line in fileinput.input(ppeFileName, inplace=1, backup='.405'): + + # in case of "mtmsr 0; isync" + line = line.replace('isync','nop') + + # skip blank line + if not line.strip(): + if pre_line: + print pre_line, + pre_line = "" + print line, + continue + + # skip comments line + if re.search("^[\s]*(//|#)", line): + if pre_line: + print pre_line, + pre_line = "" + print line, + continue + + # skip .section code except .p2align and label: + section = re.search("^[\s]*(\.[0-9a-zA-Z_]+)", line) + if section is not None and ':' not in line and \ + section.group(1) != '.p2align': + if pre_line: + print pre_line, + pre_line = "" + print line, + continue + + # apply specical 'l' rule in CombineRules for '.p2align' before a 'label:' + label = re.search("^[\s]*[\.0-9a-zA-Z_]+[:]+", line) + if label is not None: + if pre_line and pre_op == '.p2align': + second_label_ln = fileinput.lineno() + misalign = 8 - (second_label_ln - first_label_ln - 2) % 8 + if misalign in [3,4,5,6,7]: + # profile: same space, but save cycles, branch penalty is 2 + P2P_CYCLE -= misalign - 2 + if P2P_COMMENT: print "#P2P(l):" + print '\tb ' + label.group(0).split(':')[0] + print pre_line, + pre_line = "" + first_label_ln = fileinput.lineno() + if pre_line: + print pre_line, + pre_line = "" + print line, + continue + + # extract opcode field from line + ppc_op = line.split()[0] + done,match = False,False + + # detect the 2nd possible combinable instruction + if pre_line and P2P_COMBINE: + # ignore +/- signs for branch prediction + if '+' in ppc_op or '-' in ppc_op: + ppc_op = ppc_op[:-1] + if 'cmp' in pre_op and ppc_op in FuseBranches or \ + 'cmp' not in pre_op and ppc_op == pre_op: + done,match = p2p_combine(pre_line, line, pre_op, ppc_op) + if not match: + print pre_line, + else: + print pre_line, + done,match = True,False + pre_line = "" + + # detect the 1st possible combinable instruction + if not pre_line and not match and P2P_COMBINE: + if ppc_op in CombineRules.keys(): + pre_op = ppc_op + pre_line = line + done,match = True,True + else: + done,match = True,False + + # defect possible replacable instruction + if not match: + if ppc_op in ReplaceRules.keys() and P2P_REPLACE: + done = p2p_replace(line, ppc_op) + else: + print line, + done = True + + # if instruction process is not done due to error + if not done: + line_num = fileinput.lineno() + break + + # close the output file and restore the original input file + fileinput.close() + os.rename(ppeFileName+'.405', ppcFileName) + + # in case last line of the file qualified to be a pre_line and was not printed + if pre_line: + f = open(ppeFileName, 'a') + f.write(pre_line) + f.close() + + # print error debug message + if not done: + print "Error: target instruction detected at line [%d]:" % line_num + print " " + line + print " but fail to recognize instruction format." + # terminate Makefile or execution if an error is detected + sys.exit(1) + + if P2P_COMMENT and P2P_PROFILE: + f = open(ppeFileName, 'a') + f.write("#P2P: space(%d) cycle(%d)" % (P2P_SPACE,P2P_CYCLE)) + f.close() + + if P2P_VERBOSE: + print "Generated PPE assembly: " + ppeFileName + if P2P_PROFILE: + print "Optimization Profiling: " + str(P2P_SPACE*4) + " bytes, " +\ + str(P2P_CYCLE) + " cycles." + + +# ----------------------------------------------------------------------------- +# p2p_profile +# profiling how much performance and code size are saved by optimization +# +# Arguments: +# string: ppcFileName +# Return: +# list: [space, cycle] +# Variables: +# string: line, profile +# Subroutine: +# None +# ----------------------------------------------------------------------------- +def p2p_profile(ppcFileName): + f = open(ppcFileName.replace(P2P_PPC_EXT, P2P_PPE_EXT), 'r') + for line in f: + pass + f.close() + profile = re.search(r"^\#P2P: space\(([0-9\-]+)\) cycle\(([0-9\-]+)\)", line) + if profile is not None: + return [int(profile.group(1)), int(profile.group(2))] + else: + return [0,0] + +# ----------------------------------------------------------------------------- +# p2p_main: +# main of this script +# print usage info +# parse options and arguments +# process one file or a directory of files +# ----------------------------------------------------------------------------- +def p2p_main(): + + # command-line option parsing + from optparse import OptionParser + usage = "usage: %prog [options]" + version= "%prog v." + P2P_VERSION + parser = OptionParser(usage=usage, version=version) + parser.add_option("-d", "--directory", metavar="PATH", dest="ppcPath", + help="process all files in a directory given by PATH") + parser.add_option("-f", "--filename", metavar="FILE", dest="ppcFile", + help="process single file(with path in the filename)") + parser.add_option("-p", "--parallel", + action="store_true", dest="parallel", default=False, + help="processing all files in parallel processes") + parser.add_option("-s", "--statistics", + action="store_true", dest="profile", default=False, + help="optimization profiling, require comment in outputs") + parser.add_option("-c", "--combine-only", + action="store_false", dest="replace", default=True, + help="enable only combine function by disabling replace") + parser.add_option("-r", "--replace-only", + action="store_false", dest="combine", default=True, + help="enable only replace function by disabling combine") + parser.add_option("-b", "--compare branch disable", + action="store_false", dest="compare_branch", default=True, + help="only disabling fused compare branch function") + parser.add_option("-v", "--virtual double disable", + action="store_false", dest="virtual_double", default=True, + help="only disabling fused virtual double function") + parser.add_option("-e", "--eabi", + action="store_true", dest="vdw_sda", default=False, + help="enable virtual double word fusion targeting sda") + parser.add_option("-n", "--no-comment", + action="store_false", dest="comment", default=True, + help="don't leave comment mark in output file") + parser.add_option("-q", "--quiet", + action="store_false", dest="verbose", default=True, + help="don't print status messages to stdout") + (options, args) = parser.parse_args() + # global program output verbose switch + global P2P_VERBOSE; P2P_VERBOSE = options.verbose + # leave a comment mark in output files + global P2P_COMMENT; P2P_COMMENT = options.comment + # space/performance profiling function + global P2P_PROFILE; P2P_PROFILE = options.profile + # enable instruction replace functions + global P2P_REPLACE; P2P_REPLACE = options.replace + # enable instruction combine functions + global P2P_COMBINE; P2P_COMBINE = options.combine + # enable virtual double word fusion targeting sda + global P2P_VDW_SDA; P2P_VDW_SDA = options.vdw_sda + # enable only fused compare and branch function + global P2P_COMPARE_BRANCH; P2P_COMPARE_BRANCH = options.compare_branch + # enable only combined virtual double function + global P2P_VIRTUAL_DOUBLE; P2P_VIRTUAL_DOUBLE = options.virtual_double + + if P2P_VERBOSE : + print "PPC405 Assembly to PPE42 Assembly Post-Compiler Proceesor (P2P)" + print "Version: " + P2P_VERSION + + # single file processing + if options.ppcFile: + + if P2P_VERBOSE : + print "Processing signle file: " + options.ppcFile + + p2p_onefile(options.ppcFile) + + # multiple files processing + if options.ppcPath: + + if P2P_VERBOSE : + print "Accessing all files at: " + options.ppcPath + print "*Parallel Process Mode: " + ("Off", "On")[options.parallel] + + if options.profile: + bytes = 0; cycles = 0 + + fileList = [] + for root, subdirs, files in os.walk(options.ppcPath): + for file in fnmatch.filter(files, '*'+P2P_PPC_EXT): + if options.parallel : + fileList.append(os.path.join(root, file)) + else: + if options.profile: + space,cycle = p2p_profile(os.path.join(root, file)) + bytes += space*4 + cycles += cycle + else: + p2p_onefile(os.path.join(root, file)) + + if options.profile: + print "Optimization Profiling: " + str(bytes) + " bytes, " +\ + str(cycles) + " cycles." + + # parallel processing mode + if options.parallel: + from multiprocessing import Pool + p = Pool() + p.map(p2p_onefile, fileList) + p.close() + p.join() + + if P2P_VERBOSE : print "Done" + + +# ----------------------------------------------------------------------------- +# python main +if __name__ == '__main__': + p2p_main() + diff --git a/src/ppe/tools/PowerPCtoPPE/ppe42_divw.S b/src/ppe/tools/PowerPCtoPPE/ppe42_divw.S new file mode 100644 index 0000000..b1ac5b4 --- /dev/null +++ b/src/ppe/tools/PowerPCtoPPE/ppe42_divw.S @@ -0,0 +1,232 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/tools/PowerPCtoPPE/ppe42_divw.S $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +/// \file ppe42_divw.S +/// \brief PPC405 word division instructions implemented by PPE ISA +/// +/// This file includes implementation for the following PPC405 instructions +/// divw RT, RA, RB +/// +/// Note: PPE ISA specific "fused compare and branch" instructions are used +/// +/// Revision History: +/// 09-22-2014: Initial Version by daviddu +/// + + .file "ppe42_divw.S" + .section ".text" + + /* + ** Code comment notation: + ** + ** msw = most-significant (high-order) word, i.e. bits 0..31 + ** lsw = least-significant (low-order) word, i.e. bits 32..63 + ** msh = most-significant (high-order) halfword, i.e. bits 0..15 + ** lsh = least-significant (low-order) halfword, i.e. bits 16..63 + ** + ** LZ = Leading Zeroes + ** SD = Significant Digits + ** OW = Register is overwritten, previous value is lost, + ** correct if previous value is no longer needed. + ** FU = Register is not overwritten, but its value is no longer needed, + ** in another word, the register is "free for use". + ** + ** PPE GPR Registers are: R0-R10, R13, R28-R31 + ** Volatile Registers are: R0, R3-R10 + ** Non-volatile registers are R28-R31 + */ + + /* + ** Caling Convention + ** + ** R2 and R13 are never saved or restored. In ABI or EABI application + ** these registers are constant. The other touched volatile registers + ** will be saved and restored by the subroutines. Note the caller + ** wont be saving those registers because these subroutines will be + ** instrumented into caller's body without compiler knowledge. + ** + ** Note R3 is not saved and restored because it will be changed for + ** return value anyways, the p2p script will make sure to restore it. + ** Also CR is hanlded because of compare and branch, but XER/CTR/LR + ** are not hanlded because they are untouched by the instructions used. + ** + ** Stack layout: + ** + ** 0x00 -- R1, Dedicated for Stack Pointer + ** 0x04 -- slot reserved for LR + ** 0x08 -- R4, Volatile, Private + ** 0x0c -- R5, Volatile, Private + ** 0x10 -- R6, Volatile, Private + ** 0x14 -- R7, Volatile, Private + ** 0x18 -- R8, Volatile, Private + ** 0x1c -- R9, Volatile, Private + ** 0x20 -- CR, Condition Register + ** 0x24 -- + ** + ** 0x28 -- Stack Size, Must be 8-byte aligned + */ + + /* + ** Division Procedures: + ** + ** __ppe42_divwu(dividend, divisor) + ** __ppe42_divw(dividend, divisor) + ** + ** R3 = Input parameter, dividend. then Return value, quotient. + ** R4 = Input parameter, divisor. + ** R5 = Output parameter, quotient. + ** R6 = Output parameter, remainder. + ** R7 = Temporary register, counter. + ** + ** General Algorithm + ** + ** Using standard shift and subtract method to emulate + ** Note: dividend,divisor,quotient,remainder are all 32-bit integers + ** + ** Precondition Check: + ** + ** if (divisor == dividend) { + ** quotient = 1; + ** remainder = 0; + ** } + ** + ** if (divisor == 0) { + ** quotient = 0; + ** remainder = 0; + ** } + ** + ** if (divisor > dividend) { + ** quotient = 0; + ** remainder = dividend; + ** } + */ + +/*****************************************************************************/ + + /* + ** Divide Word Signed (__ppe42_divw) + ** + ** Using Divide Word Unsigned(divwu) to emulate + ** + ** dd = absolute(dividend); + ** dr = absolute(divisor); + ** [q,r] = __ppe42_divwu(dd, dr); + ** + ** quotient = q; + ** if (dividend < 0) { + ** remainder = -r; + ** if (divisor > 0) + ** quotient = -q; + ** } + ** else { + ** remainder = r; + ** if (divisor < 0) + ** quotient = -q; + ** } + */ + + .align 2 + .global __ppe42_divw + .type __ppe42_divw, @function + +__ppe42_divw: + + stwu %r1, -0x28(%r1) // allocate stack frame + + stvd %d4, 0x08(%r1) // save off r4 & r5 in stack + stvd %d6, 0x10(%r1) // save off r6 & r7 in stack + stvd %d8, 0x18(%r1) // save off r8 & r9 in stack + + mfcr %r5 // save off cr + stw %r5, 0x20(%r1) // store cr in stack + + li %r5, 1 // quotient = 1 + li %r6, 0 // remainder = 0 + cmplwbc 1, 2, %r3, %r4, __ppe42_divw_ret // ret(divisor == dividend) + + li %r5, 0 // quotient = 0 + li %r6, 0 // remainder = 0 + cmpwibc 1, 2, %r4, 0, __ppe42_divw_ret // ret(divisor == 0) + + cmpwibc 1, 1, %r3, 0, __ppe42_divw_csc // dividend(+) -> csc + neg %r3, %r3 // absolute(dividend) + li %r5, 1 // note dividend < 0 + +__ppe42_divw_csc: // <<continue sign check>> + + cmpwibc 1, 1, %r4, 0, __ppe42_divw_uns // divisor(+) -> uns + neg %r4, %r4 // absolute(divisor) + li %r6, 1 // note divisor < 0 + +__ppe42_divw_uns: // <<unsigned division>> + + mr %r8, %r5 // remember if dividend > 0 + xor %r9, %r5, %r6 // remember sign difference + + li %r5, 0 // quotient = 0 + mr %r6, %r3 // remainder = dividend + cmplwbc 1, 0, %r3, %r4, __ppe42_divw_sign // ret(divisor > dividend) + + li %r7, 32 // num_of_bits = 32 + +__ppe42_divw_sas: // <<shift and subtract loop>> + + slwi %r6, %r6, 1 // remainder <<= 1 + inslwi %r6, %r3, 1, 31 // remainder[31] = dividend[0] + slwi %r3, %r3, 1 // dividend <<= 1 + slwi %r5, %r5, 1 // quotient <<= 1 + subi %r7, %r7, 1 // num_of_bits-- + cmplwbc 1, 0, %r6, %r4, __ppe42_divw_sas // continue(remainder<divisor) + + sub %r6, %r6, %r4 // reminder -= divisor + addi %r5, %r5, 1 // quotient++ + cmpwibc 0, 2, %r7, 0, __ppe42_divw_sas // while(num_of_bits) + +__ppe42_divw_sign: // <<sign handling>> + + cmpwibc 1, 2, %r9, 0, __ppe42_divw_csh // if same sign, r5 stays + + neg %r5, %r5 // otherwise, neg(r5) + +__ppe42_divw_csh: // <<continue sign handling>> + + cmpwibc 1, 2, %r8, 0, __ppe42_divw_ret // if dividend>0, r6 stays + + neg %r6, %r6 // otherwise, neg(r6) + +__ppe42_divw_ret: // <<return subroutine>> + + mr %r3, %r5 // r3 is the default return + + lwz %r5, 0x20(%r1) // load cr from stack + mtcr0 %r5 // restore cr + + lvd %d4, 0x08(%r1) // restore r4 & r5 from stack + lvd %d6, 0x10(%r1) // restore r6 & r7 from stack + lvd %d8, 0x18(%r1) // restore r8 & r9 from stack + + lwz %r1, 0(%r1) // restore stack pointer + + blr // branch back + + .size __ppe42_divw, .-__ppe42_divw + diff --git a/src/ppe/tools/PowerPCtoPPE/ppe42_divwu.S b/src/ppe/tools/PowerPCtoPPE/ppe42_divwu.S new file mode 100644 index 0000000..98fc5ef --- /dev/null +++ b/src/ppe/tools/PowerPCtoPPE/ppe42_divwu.S @@ -0,0 +1,208 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/tools/PowerPCtoPPE/ppe42_divwu.S $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +/// \file ppe42_divwu.S +/// \brief PPC405 word division instructions implemented by PPE ISA +/// +/// This file includes implementation for the following PPC405 instructions +/// divwu RT, RA, RB +/// +/// Note: PPE ISA specific "fused compare and branch" instructions are used +/// +/// Revision History: +/// 09-22-2014: Initial Version by daviddu +/// + + .file "ppe42_divwu.S" + .section ".text" + + /* + ** Code comment notation: + ** + ** msw = most-significant (high-order) word, i.e. bits 0..31 + ** lsw = least-significant (low-order) word, i.e. bits 32..63 + ** msh = most-significant (high-order) halfword, i.e. bits 0..15 + ** lsh = least-significant (low-order) halfword, i.e. bits 16..63 + ** + ** LZ = Leading Zeroes + ** SD = Significant Digits + ** OW = Register is overwritten, previous value is lost, + ** correct if previous value is no longer needed. + ** FU = Register is not overwritten, but its value is no longer needed, + ** in another word, the register is "free for use". + ** + ** PPE GPR Registers are: R0-R10, R13, R28-R31 + ** Volatile Registers are: R0, R3-R10 + ** Non-volatile registers are R28-R31 + */ + + /* + ** Caling Convention + ** + ** R2 and R13 are never saved or restored. In ABI or EABI application + ** these registers are constant. The other touched volatile registers + ** will be saved and restored by the subroutines. Note the caller + ** wont be saving those registers because these subroutines will be + ** instrumented into caller's body without compiler knowledge. + ** + ** Note R3 is not saved and restored because it will be changed for + ** return value anyways, the p2p script will make sure to restore it. + ** Also CR is hanlded because of compare and branch, but XER/CTR/LR + ** are not hanlded because they are untouched by the instructions used. + ** + ** Stack layout: + ** + ** 0x00 -- R1, Dedicated for Stack Pointer + ** 0x04 -- slot reserved for LR + ** 0x08 -- R4, Volatile, Private + ** 0x0c -- R5, Volatile, Private + ** 0x10 -- R6, Volatile, Private + ** 0x14 -- R7, Volatile, Private + ** 0x18 -- R8, Volatile, Private + ** 0x1c -- R9, Volatile, Private + ** 0x20 -- CR, Condition Register + ** 0x24 -- + ** + ** 0x28 -- Stack Size, Must be 8-byte aligned + */ + + /* + ** Division Procedures: + ** + ** __ppe42_divwu(dividend, divisor) + ** __ppe42_divw(dividend, divisor) + ** + ** R3 = Input parameter, dividend. then Return value, quotient. + ** R4 = Input parameter, divisor. + ** R5 = Output parameter, quotient. + ** R6 = Output parameter, remainder. + ** R7 = Temporary register, counter. + ** + ** General Algorithm + ** + ** Using standard shift and subtract method to emulate + ** Note: dividend,divisor,quotient,remainder are all 32-bit integers + ** + ** Precondition Check: + ** + ** if (divisor == dividend) { + ** quotient = 1; + ** remainder = 0; + ** } + ** + ** if (divisor == 0) { + ** quotient = 0; + ** remainder = 0; + ** } + ** + ** if (divisor > dividend) { + ** quotient = 0; + ** remainder = dividend; + ** } + */ + +/*****************************************************************************/ + + /* + ** Divide Word Unsigned (__ppe42_divwu) + ** + ** The implementation uses standard shift and subtract approach. + ** The following is an example in C. Note the implementation doesnt + ** exactly follow the C example. + ** + ** num_of_bits = 32; + ** while(num_bits) { + ** dbit = (dividend & 0x80000000) >> 31; + ** remainder = (remainder << 1) | dbit; + ** dividend = dividend << 1; + ** quotient = quotient << 1; + ** num_of_bits--; + ** if(remainder < divisor) + ** continue; + ** temp = remainder - divisor; + ** qbit = !((temp & 0x80000000) >> 31); + ** quotient = quotient | qbit; + ** remainder = temp; + ** } + */ + + .align 2 + .global __ppe42_divwu + .type __ppe42_divwu, @function + +__ppe42_divwu: + + stwu %r1, -0x28(%r1) // allocate stack frame + + stvd %d4, 0x08(%r1) // save off r4 & r5 in stack + stvd %d6, 0x10(%r1) // save off r6 & r7 in stack + stvd %d8, 0x18(%r1) // save off r8 & r9 in stack + + mfcr %r5 // save off cr + stw %r5, 0x20(%r1) // store cr in stack + + li %r5, 1 // quotient = 1 + li %r6, 0 // remainder = 0 + cmplwbc 1, 2, %r3, %r4, __ppe42_divwu_ret // ret(divisor == dividend) + + li %r5, 0 // quotient = 0 + li %r6, 0 // remainder = 0 + cmpwibc 1, 2, %r4, 0, __ppe42_divwu_ret // ret(divisor == 0) + + li %r5, 0 // quotient = 0 + mr %r6, %r3 // remainder = dividend + cmplwbc 1, 0, %r3, %r4, __ppe42_divwu_ret // ret(divisor > dividend) + + li %r7, 32 // num_of_bits = 32 + +__ppe42_divwu_sas: // <<shift and subtract loop>> + + slwi %r6, %r6, 1 // remainder <<= 1 + inslwi %r6, %r3, 1, 31 // remainder[31] = dividend[0] + slwi %r3, %r3, 1 // dividend <<= 1 + slwi %r5, %r5, 1 // quotient <<= 1 + subi %r7, %r7, 1 // num_of_bits-- + cmplwbc 1, 0, %r6, %r4, __ppe42_divwu_sas // continue(remainder<divisor) + + sub %r6, %r6, %r4 // reminder -= divisor + addi %r5, %r5, 1 // quotient++ + cmpwibc 0, 2, %r7, 0, __ppe42_divwu_sas // while(num_of_bits) + +__ppe42_divwu_ret: // <<return subroutine>> + + mr %r3, %r5 // r3 is the default return + lwz %r5, 0x20(%r1) // load cr from stack + mtcr0 %r5 // restore cr + + lvd %d4, 0x08(%r1) // restore r4 & r5 from stack + lvd %d6, 0x10(%r1) // restore r6 & r7 from stack + lvd %d8, 0x18(%r1) // restore r8 & r9 from stack + + lwz %r1, 0(%r1) // restore stack pointer + + blr // branch back + + .size __ppe42_divwu, .-__ppe42_divwu + + diff --git a/src/ppe/tools/PowerPCtoPPE/ppe42_mulhw.S b/src/ppe/tools/PowerPCtoPPE/ppe42_mulhw.S new file mode 100644 index 0000000..d60ec10 --- /dev/null +++ b/src/ppe/tools/PowerPCtoPPE/ppe42_mulhw.S @@ -0,0 +1,217 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/tools/PowerPCtoPPE/ppe42_mulhw.S $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +/// \file ppe42_mulhw.S +/// \brief PPC405 word multiplication instructions implemented by PPE ISA +/// +/// This file includes implementation for the following PPC405 instructions +/// mulhw +/// +/// Note: PPE ISA specific "fused compare and branch" instructions are used +/// +/// Revision History: +/// 09-15-2014: Initial Version by daviddu +/// + + .file "ppe42_mulhw.S" + .section ".text" + + /* + ** Code comment notation: + ** + ** msw = most-significant (high-order) word, i.e. bits 0..31 + ** lsw = least-significant (low-order) word, i.e. bits 32..63 + ** msh = most-significant (high-order) halfword, i.e. bits 0..15 + ** lsh = least-significant (low-order) halfword, i.e. bits 16..63 + ** LZ = Leading Zeroes + ** SD = Significant Digits + ** OW = Register is overwritten, previous value is lost, + ** correct if previous value is no longer needed. + ** FU = Register is not overwritten, but its value is no longer needed, + ** in another word, the register is "free for use". + ** + ** PPE GPR Registers are: R0-R10, R13, R28-R31 + ** Volatile Registers are: R0, R3-R10 + ** Non-volatile registers are R28-R31 + */ + + /* + ** Caling Convention + ** + ** R2 and R13 are never saved or restored. In ABI or EABI application + ** these registers are constant. The other touched volatile registers + ** will be saved and restored by the subroutines. Note the caller + ** wont be saving those registers because these subroutines will be + ** instrumented into caller's body without compiler knowledge. + ** + ** Note R3 is not saved and restored because it will be changed for + ** return value anyways, the p2p script will make sure to restore it. + ** Also CR is hanlded because of compare and branch, but XER/CTR/LR + ** are not hanlded because they are untouched by the instructions used. + ** + ** Stack layout: + ** + ** 0x00 -- R1, Dedicated for Stack Pointer + ** 0x04 -- slot reserved for LR + ** 0x08 -- R4, Volatile, Private + ** 0x0c -- R5, Volatile, Private + ** 0x10 -- R6, Volatile, Private + ** 0x14 -- R7, Volatile, Private + ** 0x18 -- R8, Volatile, Private + ** 0x1c -- R9, Volatile, Private + ** 0x20 -- CR, Condition Register + ** 0x24 -- + ** + ** 0x28 -- Stack Size, Must be 8-byte aligned + */ + + /* + ** Multiplication Procedures: + ** + ** __ppe42_mulhwu(U,V) + ** __ppe42_mulhw(U,V) + ** __ppe42_mullw(U,V) + ** + ** R3:R4 = Input parameter, multipliers: U, V. + ** R3 = Output parameter, either product.msh or product.lsh. + ** R5-R9 = Temporary registers + ** + ** General Algorithm + ** + ** Using PPC405 ISA instruction 'mullhw' to emulate + ** Note: U,V,A,B,C,D,Product are all 32-bit integers(with msh and lsh) + ** + ** U.msh U.lsh + ** X V.msh V.lsh + ** ------------------------ + ** A.msh A.lsh + ** B.msh B.lsh + ** C.msh C.lsh + ** D.msh D.lsh + ** ------------------------ + ** Product.msw Product.lsw + ** + ** __ppe42_mulhwu: Return Product.msh (unsigned) + ** __ppe42_mulhw: Return Product.msh (signed) + ** __ppe42_mullw: Return Product.lsh + ** + ** Precondition Check: + ** + ** if( U == 0 || V == 0 ) return P=0; + */ + +/*****************************************************************************/ + + /* + ** Multiply High Word Signed (__ppe42_mulhw) + ** + ** Using Multiply High Word Unsigned(mulhwu) to emulate + ** + ** u = absolute(U); + ** v = absolute(V); + ** p = __ppe42_mulhwu(u, v); + ** if( U[0] xor V[0] ) + ** p = -p + */ + + .align 2 + .global __ppe42_mulhw + .type __ppe42_mulhw, @function + +__ppe42_mulhw: + + stwu %r1, -0x28(%r1) // allocate stack frame + + stvd %d4, 0x08(%r1) // save off r4 & r5 in stack + stvd %d6, 0x10(%r1) // save off r6 & r7 in stack + stvd %d8, 0x18(%r1) // save off r8 & r9 in stack + + mfcr %r5 // save off cr + stw %r5, 0x20(%r1) // store cr in stack + + li %r5, 0 // r5 = 0 + cmpwibc 1, 2, %r3, 0, __ppe42_mulhw_ret // U=0 -> ret + cmpwibc 1, 2, %r4, 0, __ppe42_mulhw_ret // V=0 -> ret + + cmpwibc 1, 1, %r3, 0, __ppe42_mulhw_csc // U>0 -> csc + neg %r3, %r3 // absolute(U) + li %r5, 1 // U<0 -> r5 = 1 + +__ppe42_mulhw_csc: // <<continue sign check>> + + li %r6, 0 // V>0 -> r6 = 0 + cmpwibc 1, 1, %r4, 0, __ppe42_mulhw_uns // V>0 -> uns + neg %r4, %r4 // absolute(V) + li %r6, 1 // V<0 -> r6 = 1 + +__ppe42_mulhw_uns: // <<unsigned multiplication>> + + xor %r9, %r5, %r6 // remember sign difference + + extrwi %r5, %r3, 16, 16 + srwi %r3, %r3, 16 + extrwi %r6, %r4, 16, 16 + srwi %r4, %r4, 16 + + mullhwu %r7, %r5, %r6 + srwi %r7, %r7, 16 + + mullhwu %r6, %r3, %r6 + extrwi %r8, %r6, 16, 16 + srwi %r6, %r6, 16 + add %r7, %r8, %r7 + + mullhwu %r5, %r5, %r4 + extrwi %r8, %r5, 16, 16 + srwi %r5, %r5, 16 + add %r7, %r8, %r7 + + srwi %r7, %r7, 16 + add %r7, %r7, %r6 + add %r7, %r7, %r5 + + mullhwu %r3, %r3, %r4 + add %r5, %r3, %r7 + + cmpwibc 1, 2, %r9, 0, __ppe42_mulhw_ret // if same sign, r5 stays + + neg %r5, %r5 // otherwise, neg(r5) + +__ppe42_mulhw_ret: + + mr %r3, %r5 // put return value to r3 + + lwz %r5, 0x20(%r1) // load cr from stack + mtcr0 %r5 // restore cr + + lvd %d4, 0x08(%r1) // restore r4 & r5 from stack + lvd %d6, 0x10(%r1) // restore r6 & r7 from stack + lvd %d8, 0x18(%r1) // restore r8 & r9 from stack + + lwz %r1, 0(%r1) // restore stack pointer + + blr + + .size __ppe42_mulhw, .-__ppe42_mulhw + + diff --git a/src/ppe/tools/PowerPCtoPPE/ppe42_mulhwu.S b/src/ppe/tools/PowerPCtoPPE/ppe42_mulhwu.S new file mode 100644 index 0000000..b1f2981 --- /dev/null +++ b/src/ppe/tools/PowerPCtoPPE/ppe42_mulhwu.S @@ -0,0 +1,226 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/tools/PowerPCtoPPE/ppe42_mulhwu.S $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +/// \file ppe42_mulhwu.S +/// \brief PPC405 word multiplication instructions implemented by PPE ISA +/// +/// This file includes implementation for the following PPC405 instructions +/// mulhwu +/// +/// Note: PPE ISA specific "fused compare and branch" instructions are used +/// +/// Revision History: +/// 09-15-2014: Initial Version by daviddu +/// + + .file "ppe42_mulhwu.S" + .section ".text" + + /* + ** Code comment notation: + ** + ** msw = most-significant (high-order) word, i.e. bits 0..31 + ** lsw = least-significant (low-order) word, i.e. bits 32..63 + ** msh = most-significant (high-order) halfword, i.e. bits 0..15 + ** lsh = least-significant (low-order) halfword, i.e. bits 16..63 + ** LZ = Leading Zeroes + ** SD = Significant Digits + ** OW = Register is overwritten, previous value is lost, + ** correct if previous value is no longer needed. + ** FU = Register is not overwritten, but its value is no longer needed, + ** in another word, the register is "free for use". + ** + ** PPE GPR Registers are: R0-R10, R13, R28-R31 + ** Volatile Registers are: R0, R3-R10 + ** Non-volatile registers are R28-R31 + */ + + /* + ** Caling Convention + ** + ** R2 and R13 are never saved or restored. In ABI or EABI application + ** these registers are constant. The other touched volatile registers + ** will be saved and restored by the subroutines. Note the caller + ** wont be saving those registers because these subroutines will be + ** instrumented into caller's body without compiler knowledge. + ** + ** Note R3 is not saved and restored because it will be changed for + ** return value anyways, the p2p script will make sure to restore it. + ** Also CR is hanlded because of compare and branch, but XER/CTR/LR + ** are not hanlded because they are untouched by the instructions used. + ** + ** Stack layout: + ** + ** 0x00 -- R1, Dedicated for Stack Pointer + ** 0x04 -- slot reserved for LR + ** 0x08 -- R4, Volatile, Private + ** 0x0c -- R5, Volatile, Private + ** 0x10 -- R6, Volatile, Private + ** 0x14 -- R7, Volatile, Private + ** 0x18 -- R8, Volatile, Private + ** 0x1c -- R9, Volatile, Private + ** 0x20 -- CR, Condition Register + ** 0x24 -- + ** + ** 0x28 -- Stack Size, Must be 8-byte aligned + */ + + /* + ** Multiplication Procedures: + ** + ** __ppe42_mulhwu(U,V) + ** __ppe42_mulhw(U,V) + ** __ppe42_mullw(U,V) + ** + ** R3:R4 = Input parameter, multipliers: U, V. + ** R3 = Output parameter, either product.msh or product.lsh. + ** R5-R9 = Temporary registers + ** + ** General Algorithm + ** + ** Using PPC405 ISA instruction 'mullhw' to emulate + ** Note: U,V,A,B,C,D,Product are all 32-bit integers(with msh and lsh) + ** + ** U.msh U.lsh + ** X V.msh V.lsh + ** ------------------------ + ** A.msh A.lsh + ** B.msh B.lsh + ** C.msh C.lsh + ** D.msh D.lsh + ** ------------------------ + ** Product.msw Product.lsw + ** + ** __ppe42_mulhwu: Return Product.msh (unsigned) + ** __ppe42_mulhw: Return Product.msh (signed) + ** __ppe42_mullw: Return Product.lsh + ** + ** Precondition Check: + ** + ** if( U == 0 || V == 0 ) return P=0; + */ + +/*****************************************************************************/ + + /* + ** Multiply High Word Unsigned (__ppe42_mulhwu) + ** + ** r5 = U[16:31] or U.lsh | r5 = r3 & 0xffff + ** r3 = U[0:15] or U.msh | r3 = r3 >> 16 (r3 OW) + ** r6 = V[16:31] or V.lsh | r6 = r4 & 0xffff + ** r4 = V[0:15] or V.msh | r4 = r4 >> 16 (r4 OW) + ** + ** 4th column(drop A.lsh): + ** A = U.lsh * V.lsh [32] | r7 = r5 * r6 + ** A = A.msh [16] | r7 = r7 >> 16 (r7 OW) + ** + ** 3rd column(A = A.msh + B.lsh + C.lsh): + ** B = U.msh * U.lsh [32] | r6 = r3 * r6 (r6 OW) + ** T = B.lsh [16] | r8 = r6 & 0xffff + ** B = B.msh [16] | r6 = r6 >> 16 (r6 OW) + ** A = T + A [16] | r7 = r8 + r7 (r7 OW, r8 FU) + ** + ** C = U.lsh * V.msh [32] | r5 = r5 * r4 (r5 OW) + ** T = C.lsh [16] | r8 = r5 & 0xffff (r8 OW) + ** C = C.msh [16] | r5 = r5 >> 16 (r5 OW) + ** A = T + A [16] | r7 = r8 + r7 (r7 OW, r8 FU) + ** + ** 2nd column(A = 3rd_carry + B.msh + C.msh): + ** A = A.msh [16] | r7 = r7 >> 16 (r7 OW) + ** A = A + B [16] | r7 = r7 + r6 (r7 OW, r6 FU) + ** A = A + C [16] | r7 = r7 + r5 (r7 OW, r5 FU) + ** + ** 1st column(A = D + A): + ** D = U.msh * V.msh [32] | r3 = r3 * r4 (r3 OW, r4 FU) + ** P = D + A [32] | r5 = r3 + r7 (r3, r7 FU) + ** + ** Return P(r3=r5) as Product.msw unsigned + ** + ** Note: the implementation can be even shorter, the current + ** implementation is ensuring the overflow is avoided + ** by always adding 16 bits integer together. + */ + + .align 2 + .global __ppe42_mulhwu + .type __ppe42_mulhwu, @function + +__ppe42_mulhwu: + + stwu %r1, -0x28(%r1) // allocate stack frame + + stvd %d4, 0x08(%r1) // save off r4 & r5 in stack + stvd %d6, 0x10(%r1) // save off r6 & r7 in stack + stvd %d8, 0x18(%r1) // save off r8 & r9 in stack + + mfcr %r5 // save off cr + stw %r5, 0x20(%r1) // store cr in stack + + li %r5, 0 // r5 = 0 + cmpwibc 1, 2, %r3, 0, __ppe42_mulhwu_ret // U=0 -> ret + cmpwibc 1, 2, %r4, 0, __ppe42_mulhwu_ret // V=0 -> ret + + extrwi %r5, %r3, 16, 16 + srwi %r3, %r3, 16 + extrwi %r6, %r4, 16, 16 + srwi %r4, %r4, 16 + + mullhwu %r7, %r5, %r6 + srwi %r7, %r7, 16 + + mullhwu %r6, %r3, %r6 + extrwi %r8, %r6, 16, 16 + srwi %r6, %r6, 16 + add %r7, %r8, %r7 + + mullhwu %r5, %r5, %r4 + extrwi %r8, %r5, 16, 16 + srwi %r5, %r5, 16 + add %r7, %r8, %r7 + + srwi %r7, %r7, 16 + add %r7, %r7, %r6 + add %r7, %r7, %r5 + + mullhwu %r3, %r3, %r4 + add %r5, %r3, %r7 + +__ppe42_mulhwu_ret: + + mr %r3, %r5 // put return value to r3 + + lwz %r5, 0x20(%r1) // load cr from stack + mtcr0 %r5 // restore cr + + lvd %d4, 0x08(%r1) // restore r4 & r5 from stack + lvd %d6, 0x10(%r1) // restore r6 & r7 from stack + lvd %d8, 0x18(%r1) // restore r8 & r9 from stack + + lwz %r1, 0(%r1) // restore stack pointer + + blr + + .size __ppe42_mulhwu, .-__ppe42_mulhwu + + diff --git a/src/ppe/tools/PowerPCtoPPE/ppe42_mullw.S b/src/ppe/tools/PowerPCtoPPE/ppe42_mullw.S new file mode 100644 index 0000000..59b0856 --- /dev/null +++ b/src/ppe/tools/PowerPCtoPPE/ppe42_mullw.S @@ -0,0 +1,198 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/tools/PowerPCtoPPE/ppe42_mullw.S $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +/// \file ppe42_mullw.S +/// \brief PPC405 word multiplication instructions implemented by PPE ISA +/// +/// This file includes implementation for the following PPC405 instructions +/// mullw +/// +/// Note: PPE ISA specific "fused compare and branch" instructions are used +/// +/// Revision History: +/// 09-15-2014: Initial Version by daviddu +/// + + .file "ppe42_mullw.S" + .section ".text" + + /* + ** Code comment notation: + ** + ** msw = most-significant (high-order) word, i.e. bits 0..31 + ** lsw = least-significant (low-order) word, i.e. bits 32..63 + ** msh = most-significant (high-order) halfword, i.e. bits 0..15 + ** lsh = least-significant (low-order) halfword, i.e. bits 16..63 + ** LZ = Leading Zeroes + ** SD = Significant Digits + ** OW = Register is overwritten, previous value is lost, + ** correct if previous value is no longer needed. + ** FU = Register is not overwritten, but its value is no longer needed, + ** in another word, the register is "free for use". + ** + ** PPE GPR Registers are: R0-R10, R13, R28-R31 + ** Volatile Registers are: R0, R3-R10 + ** Non-volatile registers are R28-R31 + */ + + /* + ** Caling Convention + ** + ** R2 and R13 are never saved or restored. In ABI or EABI application + ** these registers are constant. The other touched volatile registers + ** will be saved and restored by the subroutines. Note the caller + ** wont be saving those registers because these subroutines will be + ** instrumented into caller's body without compiler knowledge. + ** + ** Note R3 is not saved and restored because it will be changed for + ** return value anyways, the p2p script will make sure to restore it. + ** Also CR is hanlded because of compare and branch, but XER/CTR/LR + ** are not hanlded because they are untouched by the instructions used. + ** + ** Stack layout: + ** + ** 0x00 -- R1, Dedicated for Stack Pointer + ** 0x04 -- slot reserved for LR + ** 0x08 -- R4, Volatile, Private + ** 0x0c -- R5, Volatile, Private + ** 0x10 -- R6, Volatile, Private + ** 0x14 -- R7, Volatile, Private + ** 0x18 -- R8, Volatile, Private + ** 0x1c -- R9, Volatile, Private + ** 0x20 -- CR, Condition Register + ** 0x24 -- + ** + ** 0x28 -- Stack Size, Must be 8-byte aligned + */ + + /* + ** Multiplication Procedures: + ** + ** __ppe42_mulhwu(U,V) + ** __ppe42_mulhw(U,V) + ** __ppe42_mullw(U,V) + ** + ** R3:R4 = Input parameter, multipliers: U, V. + ** R3 = Output parameter, either product.msh or product.lsh. + ** R5-R9 = Temporary registers + ** + ** General Algorithm + ** + ** Using PPC405 ISA instruction 'mullhw' to emulate + ** Note: U,V,A,B,C,D,Product are all 32-bit integers(with msh and lsh) + ** + ** U.msh U.lsh + ** X V.msh V.lsh + ** ------------------------ + ** A.msh A.lsh + ** B.msh B.lsh + ** C.msh C.lsh + ** D.msh D.lsh + ** ------------------------ + ** Product.msw Product.lsw + ** + ** __ppe42_mulhwu: Return Product.msh (unsigned) + ** __ppe42_mulhw: Return Product.msh (signed) + ** __ppe42_mullw: Return Product.lsh + ** + ** Precondition Check: + ** + ** if( U == 0 || V == 0 ) return P=0; + */ + +/*****************************************************************************/ + + /* + ** Multiply Low Word (__ppe42_mullw) + ** + ** r5 = U[16:31] or U.lsh | r5 = r3 & 0xffff + ** r3 = U[0:15] or U.msh | r3 = r3 >> 16 (r3 OW) + ** r6 = V[16:31] or V.lsh | r6 = r4 & 0xffff + ** r4 = V[0:15] or V.msh | r4 = r4 >> 16 (r4 OW) + ** + ** B = U.msh * V.lsh | r3 = r3 * r6 (r3 OW) + ** B = B << 16 | r3 = r3 << 16 + ** C = U.lsh * V.msh | r4 = r5 * r4 (r4 OW) + ** C = C << 16 | r4 = r4 << 16 + ** A = U.lsh * V.lsh | r5 = r5 * r6 (r5 OW, r6 FU) + ** A = A + B | r5 = r5 + r3 (r3 FU) + ** P = A + C | r5 = r5 + r4 (r4 FU) + ** + ** Return P(r3=r5) as Product.lsw + ** + ** Note: there is no overflow case with this function + */ + + .align 2 + .global __ppe42_mullw + .type __ppe42_mullw, @function + +__ppe42_mullw: + + stwu %r1, -0x28(%r1) // allocate stack frame + + stvd %d4, 0x08(%r1) // save off r4 & r5 in stack + stvd %d6, 0x10(%r1) // save off r6 & r7 in stack + stvd %d8, 0x18(%r1) // save off r8 & r9 in stack + + mfcr %r5 // save off cr + stw %r5, 0x20(%r1) // store cr in stack + + li %r5, 0 // r5 = 0 + cmpwibc 1, 2, %r3, 0, __ppe42_mullw_ret // U=0 -> ret + cmpwibc 1, 2, %r4, 0, __ppe42_mullw_ret // V=0 -> ret + + extrwi %r5, %r3, 16, 16 + srwi %r3, %r3, 16 + extrwi %r6, %r4, 16, 16 + srwi %r4, %r4, 16 + + mullhwu %r3, %r3, %r6 + slwi %r3, %r3, 16 + + mullhwu %r4, %r5, %r4 + slwi %r4, %r4, 16 + + mullhwu %r5, %r5, %r6 + add %r5, %r5, %r3 + add %r5, %r5, %r4 + +__ppe42_mullw_ret: + + mr %r3, %r5 // put return value to r3 + + lwz %r5, 0x20(%r1) // load cr from stack + mtcr0 %r5 // restore cr + + lvd %d4, 0x08(%r1) // restore r4 & r5 from stack + lvd %d6, 0x10(%r1) // restore r6 & r7 from stack + lvd %d8, 0x18(%r1) // restore r8 & r9 from stack + + lwz %r1, 0(%r1) // restore stack pointer + + blr + + .size __ppe42_mullw, .-__ppe42_mullw + + diff --git a/src/ppe/tools/ppetracepp/Makefile b/src/ppe/tools/ppetracepp/Makefile new file mode 100644 index 0000000..0c52586 --- /dev/null +++ b/src/ppe/tools/ppetracepp/Makefile @@ -0,0 +1,36 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/tools/ppetracepp/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +all: ppetracepp ppe2fsp + +ppetracepp: ppetracepp.C + g++ -m32 -O3 -w -g -I./ ppetracepp.C -o ppetracepp +# g++ -O3 -w -x c++ -fPIC -g -I./ ppetracepp.C -o ppetracepp + +ppe2fsp: ppe2fsp.c ppe2fsp_cmd.c + gcc -m32 -w -g -I./ -I../../pk/trace ppe2fsp.c ppe2fsp_cmd.c -o ppe2fsp + +clean: + rm ppetracepp ppe2fsp + diff --git a/src/ppe/tools/ppetracepp/fsp-trace b/src/ppe/tools/ppetracepp/fsp-trace Binary files differnew file mode 100755 index 0000000..1d7c30c --- /dev/null +++ b/src/ppe/tools/ppetracepp/fsp-trace diff --git a/src/ppe/tools/ppetracepp/jhash.h b/src/ppe/tools/ppetracepp/jhash.h new file mode 100755 index 0000000..a310f8d --- /dev/null +++ b/src/ppe/tools/ppetracepp/jhash.h @@ -0,0 +1,167 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/tools/ppetracepp/jhash.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef _LINUX_JHASH_H +#define _LINUX_JHASH_H + +/* jhash.h: Jenkins hash support. + * + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) + * + * http://burtleburtle.net/bob/hash/ + * + * These are the credits from Bob's sources: + * + * lookup2.c, by Bob Jenkins, December 1996, Public Domain. + * hash(), hash2(), hash3, and mix() are externally useful functions. + * Routines to test the hash are included if SELF_TEST is defined. + * You can use this free for any purpose. It has no warranty. + * + * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * + * I've modified Bob's hash to be useful in the Linux kernel, and + * any bugs present are surely my fault. -DaveM + */ + +/* NOTE: Arguments are modified. */ +#define __jhash_mix(a, b, c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + +/* The golden ration: an arbitrary value */ +#define JHASH_GOLDEN_RATIO 0x9e3779b9 + +/* The most generic version, hashes an arbitrary sequence + * of bytes. No alignment or length assumptions are made about + * the input key. + */ +static inline u32 jhash(const void *key, u32 length, u32 initval) +{ + u32 a, b, c, len; + const u8 *k = (const u8*)key; + + len = length; + a = b = JHASH_GOLDEN_RATIO; + c = initval; + + while (len >= 12) { + a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); + b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); + c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); + + __jhash_mix(a,b,c); + + k += 12; + len -= 12; + } + + c += length; + switch (len) { + case 11: c += ((u32)k[10]<<24); + case 10: c += ((u32)k[9]<<16); + case 9 : c += ((u32)k[8]<<8); + case 8 : b += ((u32)k[7]<<24); + case 7 : b += ((u32)k[6]<<16); + case 6 : b += ((u32)k[5]<<8); + case 5 : b += k[4]; + case 4 : a += ((u32)k[3]<<24); + case 3 : a += ((u32)k[2]<<16); + case 2 : a += ((u32)k[1]<<8); + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + +/* A special optimized version that handles 1 or more of u32s. + * The length parameter here is the number of u32s in the key. + */ +static inline u32 jhash2(const u32 *k, u32 length, u32 initval) +{ + u32 a, b, c, len; + + a = b = JHASH_GOLDEN_RATIO; + c = initval; + len = length; + + while (len >= 3) { + a += k[0]; + b += k[1]; + c += k[2]; + __jhash_mix(a, b, c); + k += 3; len -= 3; + } + + c += length * 4; + + switch (len) { + case 2 : b += k[1]; + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + + +/* A special ultra-optimized versions that knows they are hashing exactly + * 3, 2 or 1 word(s). + * + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally + * done at the end is not done here. + */ +static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) +{ + a += JHASH_GOLDEN_RATIO; + b += JHASH_GOLDEN_RATIO; + c += initval; + + __jhash_mix(a, b, c); + + return c; +} + +static inline u32 jhash_2words(u32 a, u32 b, u32 initval) +{ + return jhash_3words(a, b, 0, initval); +} + +static inline u32 jhash_1word(u32 a, u32 initval) +{ + return jhash_3words(a, 0, 0, initval); +} + +#endif /* _LINUX_JHASH_H */ diff --git a/src/ppe/tools/ppetracepp/ppe2fsp b/src/ppe/tools/ppetracepp/ppe2fsp Binary files differnew file mode 100755 index 0000000..ea96923 --- /dev/null +++ b/src/ppe/tools/ppetracepp/ppe2fsp diff --git a/src/ppe/tools/ppetracepp/ppe2fsp.c b/src/ppe/tools/ppetracepp/ppe2fsp.c new file mode 100755 index 0000000..5613adc --- /dev/null +++ b/src/ppe/tools/ppetracepp/ppe2fsp.c @@ -0,0 +1,534 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/tools/ppetracepp/ppe2fsp.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#include "pk_trace.h" +#include "ppe2fsp.h" +#include "trac_interface.h" +#include <arpa/inet.h> +#include <string.h> +#include <stdint.h> + +#define TRACE_BUF_VERSION 0x01 /*!< Trace buffer version */ +#define TRACE_FIELDTRACE 0x4654 /*!< Field Trace - "FT" */ +#define TRACE_FIELDBIN 0x4644 /*!< Binary Field Trace - "FD" */ + +#define TRAC_TIME_REAL 0 // upper 32 = seconds, lower 32 = nanoseconds +#define TRAC_TIME_50MHZ 1 +#define TRAC_TIME_200MHZ 2 +#define TRAC_TIME_167MHZ 3 // 166666667Hz + +typedef struct +{ + trace_entry_stamp_t stamp; + trace_entry_head_t head; + union + { + uint8_t data[PK_TRACE_MAX_BINARY + 1]; //add 1 byte for padding + uint32_t parms[PK_TRACE_MAX_PARMS]; + }; + uint32_t size; +}largest_fsp_entry_t; + +typedef struct +{ + union + { + uint8_t binary_data[PK_TRACE_MAX_BINARY + 1]; + struct + { + uint8_t rsvd[(PK_TRACE_MAX_BINARY + 1) - (PK_TRACE_MAX_PARMS * sizeof(uint32_t))]; + uint32_t parms[PK_TRACE_MAX_PARMS]; + }; + }; + PkTraceEntryFooter footer; +}LargestPpeEntry; + +//convert a ppe timestamp to an fsp trace timestamp +uint64_t ppe2fsp_time(uint64_t ppe_time, uint32_t hz) +{ + uint32_t seconds; + uint32_t remainder; + uint32_t nseconds; + + //convert from ppe ticks to seconds and nanoseconds + seconds = ppe_time / hz; + remainder = ppe_time - (((uint64_t)seconds) * hz); + nseconds = (((uint64_t)remainder) * 1000000000) / hz; + return (((uint64_t)seconds) << 32) | nseconds; +} + +//Writes an fsp trace entry to the fsp trace buffer +fsp_put_entry(trace_buf_head_t* tb, largest_fsp_entry_t* fte, size_t entry_size, uint32_t bytes_left) +{ + char* buffer = ((char*)tb) + sizeof(trace_buf_head_t); + char* tb_start; + char* fte_start; + uint32_t copy_bytes; + + if(entry_size <= bytes_left) + { + tb_start = buffer + bytes_left - entry_size; + fte_start = (char*)fte; + copy_bytes = entry_size; + } + else + { + tb_start = buffer; + fte_start = ((char*)fte) + (entry_size - bytes_left); + copy_bytes = bytes_left; + } + + memcpy(tb_start, fte_start, copy_bytes); +} + + +//convert a ppe trace entry to an fsp trace entry +size_t pte2fte(PkTraceBuffer* ptb, + LargestPpeEntry* pte, + size_t pte_size, + largest_fsp_entry_t* fte, + uint64_t ppe_time64) +{ + size_t entry_size; + PkTraceGeneric* pte_footer = &pte->footer.generic; + uint32_t format; + uint32_t hash32; + uint32_t hash32_partial; + uint32_t* parm_start; + uint32_t parm_bytes; + uint64_t fsp_time64; + + //convert the ppe trace time to an fsp trace time + fsp_time64 = ppe2fsp_time(ppe_time64, ntohl(ptb->hz)); + + //fill in the 64 bit timestamp + fte->stamp.tbh = htonl((uint32_t)(fsp_time64 >> 32)); + fte->stamp.tbl = htonl((uint32_t)(fsp_time64 & 0x00000000ffffffffull)); + + //use the ppe instance id as the thread id. + fte->stamp.tid = htonl((uint32_t)ntohs(ptb->instance_id)); + + //merge the hash prefix and the string_id fields together for a 32 bit hash value + hash32 = ((uint32_t)ntohs(ptb->hash_prefix)) << 16; + hash32 |= pte_footer->string_id; + fte->head.hash = htonl(hash32); + + //generate the 32bit hash value for a partial trace entry in case it's needed + hash32_partial = ((uint32_t)ntohs(ptb->hash_prefix)) << 16; + hash32_partial |= ntohs(ptb->partial_trace_hash); + + //set the line number to 1 + fte->head.line = htonl(1); + + //determine the FSP trace format + format = PK_GET_TRACE_FORMAT(pte_footer->time_format.word32); + if(format == PK_TRACE_FORMAT_BINARY) + { + fte->head.tag = htons(TRACE_FIELDBIN); + } + else + { + fte->head.tag = htons(TRACE_FIELDTRACE); + } + + parm_start = (uint32_t*)(((char*)pte) + (sizeof(LargestPpeEntry) - pte_size)); + + //fill in the parameters/binary data and size at the end + switch(format) + { + + case PK_TRACE_FORMAT_TINY: + //one or 0 parameters + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + sizeof(uint32_t); + fte->parms[0] = htonl((uint32_t)(pte_footer->parm16)); + fte->head.length = htons(sizeof(uint32_t)); + parm_bytes = 0; + break; + + case PK_TRACE_FORMAT_BIG: + //1 - 4 parameters + // + //If the trace entry data is incomplete (not all parm data + //had been written at the time the trace was captured) then + //we will write a trace to the fsp buffer that says + //"PARTIAL TRACE ENTRY. HASH_ID = %d" + if(pte_footer->complete) + { + parm_bytes = pte_footer->bytes_or_parms_count * sizeof(uint32_t); + fte->head.length = htons(parm_bytes + sizeof(uint32_t)); + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + parm_bytes + sizeof(uint32_t); + } + else + { + parm_bytes = 0; + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + sizeof(uint32_t); + fte->parms[0] = fte->head.hash; //already corrected for endianess + fte->head.hash = htonl(hash32_partial); + fte->head.length = htons(sizeof(uint32_t)); + } + break; + + case PK_TRACE_FORMAT_BINARY: + //If the trace entry data is incomplete (not all parm data + //had been written at the time the trace was captured) then + //we will write a trace to the fsp buffer that says + //"PARTIAL TRACE ENTRY. HASH_ID = %d" + if(pte_footer->complete) + { + parm_bytes = pte_footer->bytes_or_parms_count; + fte->head.length = htons((uint16_t)parm_bytes); + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + parm_bytes; + + //pad to 4 byte boundary + entry_size = (entry_size + 3) & ~3; + } + else + { + parm_bytes = 0; + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + sizeof(uint32_t); + fte->parms[0] = fte->head.hash; + fte->head.hash = htonl(hash32_partial); + fte->head.length = htons(sizeof(uint32_t)); + fte->head.tag = htons(TRACE_FIELDTRACE); + } + break; + + + default: + entry_size = 0; + parm_bytes = 0; + break; + } + + //copy parameter bytes to the fsp entry if necessary + if(parm_bytes) + { + memcpy(fte->data, parm_start, parm_bytes); + } + + //add the entry size to the end + if(entry_size) + { + uint32_t new_entry_size = entry_size + sizeof(uint32_t); + *((uint32_t*)(((char*)fte) + entry_size)) = htonl(new_entry_size); + entry_size = new_entry_size; + } + + return entry_size; +} + +//retrieve a ppe trace entry from a ppe trace buffer +size_t ppe_get_entry(PkTraceBuffer* tb, uint32_t offset, LargestPpeEntry* pte) +{ + uint32_t mask = ntohs(tb->size) - 1; + PkTraceEntryFooter* footer; + size_t entry_size; + size_t parm_size; + char* dest = (char*)pte; + uint32_t format; + uint32_t start_index; + uint32_t bytes_left; + uint32_t bytes_to_copy; + + //Find the footer in the circular buffer + footer = (PkTraceEntryFooter*)(&tb->cb[(offset - sizeof(PkTraceEntryFooter)) & mask]); + + //always correct endianess for the time and string id words + pte->footer.generic.time_format.word32 = ntohl(footer->generic.time_format.word32); + pte->footer.generic.string_id = ntohs(footer->generic.string_id); + + //only need to byte swap the parm16 value if this is a tiny format + pte->footer.generic.parm16 = footer->generic.parm16; + + //use footer data to determine the length of the binary data or parameters + format = PK_GET_TRACE_FORMAT(pte->footer.generic.time_format.word32); + switch(format) + { + case PK_TRACE_FORMAT_TINY: + pte->footer.generic.parm16 = ntohs(pte->footer.generic.parm16); + parm_size = 0; + entry_size = sizeof(PkTraceEntryFooter); + break; + + case PK_TRACE_FORMAT_BIG: + parm_size = pte->footer.generic.bytes_or_parms_count * sizeof(uint32_t); + entry_size = sizeof(PkTraceEntryFooter); + break; + + case PK_TRACE_FORMAT_BINARY: + parm_size = pte->footer.generic.bytes_or_parms_count; + entry_size = sizeof(PkTraceEntryFooter); + break; + + default: + entry_size = 0; + parm_size = 0; + break; + } + + //pad to 8 byte boundary + parm_size = (parm_size + 7) & ~0x00000007ul; + + //add the parameter size to the total entry size + entry_size += parm_size; + + //copy the entry from the circular buffer to pte + start_index = (offset - entry_size) & mask; + bytes_left = ntohs(tb->size) - start_index; + + //only copy up to the end of the circular buffer + if(parm_size < bytes_left) + { + bytes_to_copy = parm_size; + } + else + { + bytes_to_copy = bytes_left; + } + + dest += sizeof(LargestPpeEntry) - entry_size; + memcpy(dest, &tb->cb[start_index], bytes_to_copy); + + //now copy the rest of the data starting from the beginning of the + //circular buffer. + if(bytes_to_copy < parm_size) + { + memcpy(dest + bytes_to_copy, tb->cb, parm_size - bytes_to_copy); + } + + //return the size of the entry + return entry_size; +} + +//convert a ppe trace buffer to an fsp trace buffer +int ppe2fsp(void* in, unsigned long in_size, void* out, unsigned long* io_size) +{ + PkTraceBuffer* ptb = (PkTraceBuffer*)in; + trace_buf_head_t* ftb = (trace_buf_head_t*)out; + uint32_t ppe_bytes_left; + uint32_t fsp_bytes_left; + int rc = 0; + uint32_t ptb_offset; + PkTraceEntryFooter* ptb_te; + uint64_t ppe_time64; + uint32_t fte_size, pte_size; + uint32_t fsp_te_count = 0; + uint32_t time_diff32, prev_time32, new_time32; + PkTraceGeneric* pte_footer; + largest_fsp_entry_t fte; + LargestPpeEntry pte; + uint64_t time_adj64; + + do + { + if(!ptb || !ftb || !io_size) + { + rc = P2F_NULL_POINTER; + break; + } + + if(ntohs(ptb->version) != PK_TRACE_VERSION) + { + rc = P2F_INVALID_VERSION; + break; + } + + //check that the input buffer is large enough to have a ppe trace buffer + if(in_size < (((uint32_t)(&ptb->cb[0])) - (uint32_t)(ptb))) + { + rc = P2F_INPUT_BUFFER_TOO_SMALL; + break; + } + + //initialize some locals + fsp_bytes_left = *io_size - sizeof(trace_buf_head_t); + ppe_bytes_left = ntohs(ptb->size); + ptb_offset = ntohl(ptb->state.offset); + if(htonl(1) == 1) + { + time_adj64 = ptb->time_adj64; + } + else + { + time_adj64 = ntohl((uint32_t)(ptb->time_adj64 >> 32)); + time_adj64 |= ((uint64_t)(ntohl((uint32_t)(ptb->time_adj64 & 0x00000000ffffffff)))) << 32; + } + + //make sure the ppe buffer size is a power of two + if((ppe_bytes_left - 1) & ppe_bytes_left) + { + //size is not a power of two + rc = P2F_INVALID_INPUT_SIZE; + break; + } + + //The ppe bytes field should always be a multiple of 8 + if(ptb_offset & 0x7) + { + rc = P2F_INVALID_PPE_OFFSET; + break; + } + + //make sure there is enough room for the fsp header + if(*io_size < sizeof(trace_buf_head_t)) + { + rc = P2F_OUTPUT_BUFFER_TOO_SMALL; + break; + } + + + //initialize the fsp header + ftb->ver = TRACE_BUF_VERSION; + ftb->hdr_len = sizeof(trace_buf_head_t); + ftb->time_flg = TRAC_TIME_REAL; + ftb->endian_flg = 'B'; //big endian + memcpy(ftb->comp, ptb->image_str, sizeof(ftb->comp)); + ftb->times_wrap = htonl(1); + ftb->size = htonl(sizeof(trace_buf_head_t) + sizeof(uint32_t)); + ftb->next_free = htonl(sizeof(trace_buf_head_t)); + ftb->extracted = htonl(0); + ftb->te_count = htonl(0); + + //find the latest timestamp so that we can work back from there + ppe_time64 = ((uint64_t)(ntohl(ptb->state.tbu32) & 0xefffffff)) << 32; + pte_size = ppe_get_entry(ptb, ptb_offset, &pte); + prev_time32 = PK_GET_TRACE_TIME(pte.footer.generic.time_format.word32); + ppe_time64 |= prev_time32; + + //process all of the input bytes one trace entry at a time + //from newest to oldest (backwards) until we run out of input bytes or + //we run out of output space. + while(1) + { + //check if we have enough data for a ppe footer + if(ppe_bytes_left < sizeof(PkTraceEntryFooter)) + { + break; + } + + //get the next ppe entry + pte_size = ppe_get_entry(ptb, ptb_offset, &pte); + + //Stop if there are no more entries to retrieve from the ppe trace buffer + if(!pte_size) + { + break; + } + pte_footer = &pte.footer.generic; + + //mark the entry as incomplete if we didn't have enough data + //for the entire entry + if(pte_size > ppe_bytes_left) + { + pte_footer->complete = 0; + ppe_bytes_left = 0; + } + else + { + ppe_bytes_left -= pte_size; + ptb_offset -= pte_size; + } + + //Calculate the 64 bit timestamp for this entry.... + //On PPE, getting the timestamp is not done atomically with writing + //the entry to the buffer. This means that an entry with an older + //timestamp could possibly be added to the buffer after an entry + //with a newer timestamp. Detect this condition by checking if the + //time difference is bigger than the max difference. The max + //difference is enforced by the PPE having a trace added on a + //shorter time boundary (using a timer). + new_time32 = PK_GET_TRACE_TIME(pte_footer->time_format.word32); + time_diff32 = prev_time32 - new_time32; + + if(time_diff32 > ntohl(ptb->max_time_change)) + { + time_diff32 = new_time32 - prev_time32; + ppe_time64 += time_diff32; + } + else + { + ppe_time64 -= time_diff32; + } + + //save off the lower 32bit timestamp for the next iteration + prev_time32 = new_time32; + + //convert the ppe trace entry to an fsp trace entry + fte_size = pte2fte(ptb, &pte, pte_size, &fte, ppe_time64 + time_adj64); + + //fit as much of the entry into the fsp trace buffer as possible + fsp_put_entry(ftb, &fte, fte_size, fsp_bytes_left); + + //update the fsp trace entry count + fsp_te_count++; + + //stop if there is no more room left in the fsp trace buffer + if(fte_size >= fsp_bytes_left) + { + fsp_bytes_left = 0; + ftb->times_wrap = htonl(1); + break; + } + else + { + fsp_bytes_left -= fte_size; + } + }//while(1) + + + //shift the trace data up if there is space to do so + if(fsp_bytes_left) + { + char* dest = ((char*)ftb) + sizeof(trace_buf_head_t); + char* src = dest + fsp_bytes_left; + size_t data_size = *io_size - sizeof(trace_buf_head_t) - fsp_bytes_left; + memmove(dest, src, data_size); + } + + //update the fsp header to reflect the true size and entry count + ftb->te_count = htonl(fsp_te_count); + + //inform the caller of how many bytes were actually used + *io_size -= fsp_bytes_left; + + //shrink the size field to what we actually ended up using + ftb->size = htonl(*io_size); + + }while(0); + + return rc; +} + + + diff --git a/src/ppe/tools/ppetracepp/ppe2fsp.h b/src/ppe/tools/ppetracepp/ppe2fsp.h new file mode 100644 index 0000000..d2065be --- /dev/null +++ b/src/ppe/tools/ppetracepp/ppe2fsp.h @@ -0,0 +1,34 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/tools/ppetracepp/ppe2fsp.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ + + +#define P2F_NULL_POINTER 1 +#define P2F_INVALID_INPUT_SIZE 2 +#define P2F_INVALID_PPE_OFFSET 3 +#define P2F_OUTPUT_BUFFER_TOO_SMALL 4 +#define P2F_INPUT_BUFFER_TOO_SMALL 5 +#define P2F_INVALID_VERSION 6 + +int ppe2fsp(void* in, unsigned long in_size, void* out, unsigned long* io_size); diff --git a/src/ppe/tools/ppetracepp/ppe2fsp_cmd.c b/src/ppe/tools/ppetracepp/ppe2fsp_cmd.c new file mode 100644 index 0000000..8846a9b --- /dev/null +++ b/src/ppe/tools/ppetracepp/ppe2fsp_cmd.c @@ -0,0 +1,139 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/tools/ppetracepp/ppe2fsp_cmd.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#include <stdio.h> +#include "ppe2fsp.h" +#include "pk_trace.h" + +#define MAX_INPUT_SIZE 0x2040 //8k +#define MAX_OUTPUT_SIZE (4 * MAX_INPUT_SIZE) + +char* inbuf[MAX_INPUT_SIZE]; +char* outbuf[MAX_OUTPUT_SIZE]; +; +int main(int argc, char** argv) +{ + FILE* in; + FILE* out; + size_t input_size; + size_t output_size; + size_t bytes_written; + int rc = -1; + + do + { + if(argc > 3) + { + fprintf(stderr, "Usage: %s [input file] [output file]\n", argv[0]); + } + + if(argc < 3) + { + out = stdout; + } + else + { + //open the output file for writing + out = fopen(argv[2], "w"); + if(!out) + { + perror("failed to open file for writing"); + break; + } + } + + if(argc < 2) + { + in = stdin; + } + else + { + //open the input file for reading + in = fopen(argv[1], "r"); + if(!in) + { + perror("failed to open file for reading"); + break; + } + } + + //read the input stream until we reach EOF or the max size + input_size = fread(inbuf, 1, MAX_INPUT_SIZE, in); + if(!feof(in)) + { + if(ferror(in)) + { + perror("failed to read input file"); + break; + } + else + { + fprintf(stderr, "Input stream exceeds max size of %d bytes. Exiting.\n", MAX_INPUT_SIZE); + break; + } + } + + output_size = MAX_OUTPUT_SIZE; + + //Actual size of output buffer will be set upon successful completion + rc = ppe2fsp(inbuf, input_size, outbuf, &output_size); + if(rc) + { + fprintf(stderr, "Failed converting ppe trace to fsp trace. rc = %d\n", rc); + if(rc == P2F_INVALID_VERSION) + { + fprintf(stderr, "PPE trace buffer must be version %d.\n", PK_TRACE_VERSION); + } + break; + } + + rc = -1; + //operation was successful. Write out the fsp trace data + bytes_written = fwrite(outbuf, 1, output_size, out); + if(bytes_written != output_size) + { + if(ferror(out)) + { + perror("Failed to write output stream"); + break; + } + fprintf(stderr, "Failure: Only able to write %d of %d bytes to output stream\n", bytes_written, output_size); + break; + } + + fclose(in); + fclose(out); + fclose(stderr); + + rc = 0; + }while(0); + + return rc; +} + + + + + + diff --git a/src/ppe/tools/ppetracepp/ppetracepp b/src/ppe/tools/ppetracepp/ppetracepp Binary files differnew file mode 100755 index 0000000..61b5f04 --- /dev/null +++ b/src/ppe/tools/ppetracepp/ppetracepp diff --git a/src/ppe/tools/ppetracepp/ppetracepp.C b/src/ppe/tools/ppetracepp/ppetracepp.C new file mode 100755 index 0000000..c36cf35 --- /dev/null +++ b/src/ppe/tools/ppetracepp/ppetracepp.C @@ -0,0 +1,946 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/tools/ppetracepp/ppetracepp.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ + +/* +# *** ppetracepp - a fsp/common Linux trace pre processor +# this one replaces the trace strings by the corresponding hash value +# (i.e. the complete call to trace_ppe_hash is replaced) + +# *** Usage +# +# prepend compiler call with the call of this pre processor, i.e if you have +# $(CC) $(CFLAGS) -o $@ $< +# in your Makefile change it to this: +# ppetracepp $(CC) $(CFLAGS) -o $@ $< +# ppetracepp will use "$(CC) -E" to call the C pre processor "cpp". +# you can set a env var "REALCPP" to the name of a program to select +# a different programm as cpp +# +# ppetracepp creates a file "$target.ppe.hash" with the trace strings and the hash values. +# +# to enable debug mode set envvar PPETRACEPPDEBUG to 1 or give '-d' as first arg + +# *** Change History +# +# 2003-02-26 RBa created from scratch +# 2003-02-28 RBa add C++ support (C++ interface uses own type for the hash) +# 2003-05-28 RBa if cc should link instead of compile just call compiler +# 2003-07-11 AGe Change search alg. slightly and put just format back +# 2003-07-25 RBa just call gcc if called to link instead to compile +# eat argument for option -x +# 2003-11-26 RBa fix c/c++ algo: compile as c++ if realcc=*g++ +# 2004-02-02 RBa remove explicit test whether source file is readable +# it is obsolete and might lead to an error if afs is used +# 2004-02-13 RBa add support for dependency generation (-MD/-MG, -MF) +# don't prepend './' to object filename +# 2006-04-19 RBa rewrite trace_ppe_write_all support, handle C and C++ the same +# 2006-05-24 RBa fix handling of missing -o ; add TRAC_PPVER for macro/API version +# 2006-09-15 RBa add handling of \" in trace format strings ; reduce non-error output +# put object file in current dir if no -o given +# 2007-03-22 RBa handle more gcc options (-i) ; protect " in call to shell +# store output of cpp as "unmodified" output for debug +# only write string/hash file if strings found +# 2012-09-24 hlava Rewritten as C program for better build performance (was perl) +*/ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <string> +#include <time.h> +#include <fcntl.h> +#include <map> +#include <vector> + +#include <sys/types.h> +typedef u_int32_t u32 ; +typedef u_int8_t u8 ; +#include <jhash.h> + +using namespace std; + +static string version = "2.0"; +static string macro_version = "1"; + +static bool debug = false; +#define dprintf(format, ...) if (debug) { printf(format, ##__VA_ARGS__); fflush(stdout); } +static map<string,string> hashtab; +static string hashtype; +static string hashtype_suffix; + +static string tmp; +static string cmd; +static FILE* CPP = NULL; // pipe from preprocessor +static FILE* CC = NULL; // pipe to compiler +static FILE* DEBUG = NULL; +static FILE* DEBUGIN = NULL; + +//***************************************************************************** +// replace_substr +//***************************************************************************** +void replace_substr(std::string& str, const std::string& oldStr, const std::string& newStr) +{ + size_t pos = 0; + while((pos = str.find(oldStr, pos)) != std::string::npos) + { + str.replace(pos, oldStr.length(), newStr); + pos += newStr.length(); + } + +} + +//***************************************************************************** +// fileparse +//***************************************************************************** +void fileparse(const string& in_str, string& name, string& dir, string& suff) +{ + string str(in_str); + size_t pos; + name = ""; + dir = ""; + suff = ""; + pos = str.find_last_of('.'); + if (pos != string::npos) + { + suff = str.substr(pos); + str = str.substr(0, pos); + } + pos = str.find_last_of('/'); + if (pos != string::npos) + { + name = str.substr(pos+1); + str = str.substr(0, pos+1); + } + dir = str; +} + +static const size_t TRACE_PPE_HASH_LEN = 13; +//***************************************************************************** +// chop_up_line +//***************************************************************************** +bool chop_up_line(string& in_line, string& prefix, string& strings, string& salt, string& suffix) +{ + // First see if this line matches the pattern we're looking for + // Since this will return false 95%+ of the time this function it called, we do it + // before doing any other init for performance reasons. + size_t pos = in_line.find("trace_ppe_hash"); + if (pos == string::npos) { return(false); } + + // trace_ppe_hash ( "..." ".." "..." , 2 ) + // regex: PREFIX 'trace_ppe_hash' space '(' space STRINGS space ',' space NUMBER space ')' SUFFIX + // STRINGS: '"' .* '"' space? + + + // Original perl magic incantation: + // while($line =~ m/^(.*?)trace_ppe_hash\s*\(\s*((".*?(?<!\\)"\s*)+),\s*(-?\d+)\s*\)(.*)$/) { + // ($prefix, $strings, $salt, $suffix) = ($1, $2, $4, $5); + // + // Decrypting the magic pattern matching... + // (.*?) => $1 = everything up to the word "trace_ppe_hash" + // trace_ppe_hash = delimiter + // \s*\(\s* = delimiter = <0-n whitespace chars>, left paren, <0-n whitespace chars> + // ((".*?(?<!\\)"\s*)+) => $2 = double-quote, some chars up to last closing double-quote ($3 used for nested regex) + // ,\s* = delimiter = comma followed by some whitespace + // (-?\d+)\s*\)(.*) => $4 and $5 + // $/) = end of the line input string + string line(in_line); + prefix = ""; + strings = ""; + salt = ""; + suffix = ""; + size_t pos1; + size_t pos2; + size_t pos3; + + pos1 = pos + 14; // pos1 = after "trace_ppe_hash" + pos2 = line.find("(", pos1); + if (pos2 == string::npos) { return(false); } + ++pos2; + pos3 = line.find("\"", pos2); + if (pos3 == string::npos) { return(false); } + dprintf("--------\nchop_up_line: Passed basic checks. line= %s\n", line.c_str()); + dprintf("pos1=%d, pos2=%d, pos3=%d\n", pos1, pos2, pos3); + if ((pos1 != (pos2-1)) && (line.find_first_not_of(" \t", pos1, (pos2-pos1)+1) != string::npos)) { return(false); } //non-whitespace? + if ((pos2 != pos3) && (line.find_first_not_of(" \t", pos2, (pos3-pos2)) != string::npos)) { return(false); } //non-whitespace? + + // Get the prefix data + dprintf(">chop_up_line(\"%s\",...)\n", line.c_str()); + prefix = line.substr(0, pos); + line = line.substr(pos + TRACE_PPE_HASH_LEN); + dprintf(" prefix=\"%s\"\n", prefix.c_str()); + + // Get the strings and join/fix them: Store all strings between paired double-quotes up to the + // first comma not inside a string + pos = line.find_first_of('('); + if (pos == string::npos) { return(false); } + line = line.substr(pos + 1); + strings = ""; + while(!line.empty()) + { + pos = line.find_first_of(','); + pos1 = line.find_first_of('"'); + if ((pos1 == string::npos) || ((pos != string::npos) && (pos < pos1))) { break; } // found comma before next quote + pos2 = line.find_first_of('"', (pos1+1)); + if (pos2 == string::npos) { return(false); } // unbalanced quotes! + while(line[pos2-1] == '\\') // skip escaped quotes in the string (they're not the ending quote) + { + pos2 = line.find_first_of('"', (pos2+1)); + if (pos2 == string::npos) { return(false); } // unbalanced quotes! + } + if (!strings.empty()) { strings += " "; } + strings += line.substr(pos1, (pos2-pos1)+1); + line = line.substr(pos2+1); + } + replace_substr(strings, "\" \"", ""); + replace_substr(strings, "\\\"", "ESCAPEDQUOTE"); + replace_substr(strings, "\"", ""); + replace_substr(strings, "ESCAPEDQUOTE", "\""); + // Remove trailing whitespace ah20130717 + pos = strings.find_last_not_of(" \t\n"); + if ((pos != string::npos) && (pos < (strings.length()-1))) + { + strings = strings.substr(0, pos+1); + } + + dprintf(" strings>%s<\n", strings.c_str()); + + // Get the salt + pos = line.find(","); + if (pos != string::npos) { line = line.substr(pos+1); } + pos = line.find_first_of(')'); + if (pos == string::npos) { return(false); } + salt = line.substr(0, pos); + line = line.substr(pos+1); + //dprintf(" salt=\"%s\"\n", salt.c_str()); + pos = salt.find_first_not_of(" \t\n"); + if (pos == string::npos) { return(false); } + salt = salt.substr(pos); + pos = salt.find_last_not_of(" \t\n"); + if (pos == string::npos) { return(false); } + salt = salt.substr(0, pos+1); + dprintf(" salt=\"%s\"\n", salt.c_str()); + + // Get the suffix (i.e. the rest) + suffix = line; + if (suffix[suffix.length()-1] == '\n') { suffix = suffix.substr(0, suffix.length()-1); } + dprintf(" suffix=\"%s\"\n<chop_up_line() returning true\n", suffix.c_str()); + + return(true); +} + +//***************************************************************************** +// get_format_string +//***************************************************************************** +int get_format_string(const string& in_str, string& format) +{ + int format_salt = 0; + size_t pos; + size_t pos_end; + string str(in_str); + // (@format_param) = ($strings =~ /(%[#0\- +'I]*\d*(?:\.\d*)?[hlLqjzt]*[diouxXeEfFgGaAcsCSpn])/g); + // $format = join(',', @format_param); + // Decrypting the regular expression magic... + // (%[#0\- +'I]*\d*(?:\.\d*)?[hlLqjzt]*[diouxXeEfFgGaAcsCSpn]) + + format = ""; + while(!str.empty()) + { + pos = str.find("%"); + if (pos == string::npos) { break; } + if (pos == (str.length()-1)) { break; } // last char in string? just skip it + if (str[pos+1] == '%') // double percent sign? just skip first one + { + str = str.substr(pos+1); + continue; + } + pos_end = str.find_first_of("cdieEfgGosuxXpn", pos); // find formatting specifier + if (pos_end == string::npos) + { + fprintf(stderr, "ERROR: ppetracepp could not parse trace formatting string \"%s\" in \"%s\"\n", str.c_str(), in_str.c_str()); + break; + } + + if (!format.empty()) + format += ","; + format += str.substr(pos, (pos_end-pos)+1); + ++format_salt; + + str = str.substr(pos_end+1); + } + // Correct for escaped percent signs + string temp_str(in_str); + while((pos = temp_str.find("%%")) != string::npos) + { + if (pos < (temp_str.length()-2)) // Not the last thing in the string? + { + dprintf(" decrementing salt value %d\n", format_salt); + --format_salt; + temp_str = temp_str.substr(pos+2); + } + else + { + temp_str = ""; + } + } + + return(format_salt); +} + +#define BUF_SIZE 40 +//***************************************************************************** +// get_hash +//***************************************************************************** +void get_hash(const string& i_str, const unsigned int salt_num, string& hash32, string& hash16) +{ + string str(i_str); + unsigned int hash_num = 0; + char buf[BUF_SIZE]; + + hash16 = ""; + hash32 = ""; + dprintf(">get_hash(\"%s\",%d)\n", str.c_str(), salt_num); + + // Call jhash function to get the hash value + hash_num = jhash((void*)str.c_str(), str.length(), salt_num); + dprintf("jhash() returned: %u\n", hash_num); + sprintf(buf, "%u", hash_num & 0x0000ffff); + hash16 = buf; + sprintf(buf, "%u", ((salt_num << 16) | (hash_num & 0x0000ffff))); + hash32 = buf; + + // validate the hash value + size_t pos = hash32.find_first_not_of("0123456789"); + if (pos != string::npos) + { + fprintf(stderr, "trexhash error: %s\n", hash32.c_str()); + fprintf(stderr, "for call <<%s>>\n", cmd.c_str()); + exit(1); + } + +//removing this since it doesn't seem to have any affect on the output +#if 0 + // If hash is empty, use the sum of the ord values in the original string + if ((hash == "")||(hash == "0")) + { + unsigned int len = str.length(); + unsigned int hash_num = 0; + //unsigned char conv_buf[2] = { '\0', '\0' }; + u_int8_t conv_num; + for (unsigned int i=0; i < len; ++i) + { + //conv_buf[0] = str[i]; + conv_num = (u_int8_t)str[i]; + hash_num += (unsigned int)conv_num; + } + } +#endif + + dprintf("<get_hash(\"%s\",%d) returned hash: %s\n", str.c_str(), salt_num, hash32.c_str()); +} + +//***************************************************************************** +// parse_line +//***************************************************************************** +void parse_line(map<string,string>& rhash, string& line, string& out_line) +{ + // NOTE: "line" arg may get modified by this function! Caller must not assume it's unchanged. + string format; + string prefix; + string strings; + string tmp; + string salt; + string hash16; + string hash32; + int salt_num; + int format_salt; + string suffix; + string write_all_suffix; + size_t pos; + + out_line = ""; + // trace_ppe_hash ( "..." ".." "..." , 2 ) + // regex: PREFIX 'trace_ppe_hash' space '(' space STRINGS space ',' space NUMBER space ')' SUFFIX + // STRINGS: '"' .* '"' space? + + //while($line =~ m/^(.*?)trace_ppe_hash\s*\(\s*((".*?(?<!\\)"\s*)+),\s*(-?\d+)\s*\)(.*)$/) { + // Attempt to approximate the above amazing perl regex... + while( chop_up_line(line, prefix, strings, salt, suffix) ) + { + //dprintf("\n\nprefix = %s\nstrings = %s\nsalt = %s\nsuffix = %s\n", + // prefix.c_str(), strings.c_str(), salt.c_str(), suffix.c_str()); + // is this a trace_ppe_write_all call? + pos = prefix.find("trace_ppe_write_all"); + if (pos != string::npos) + { + // yes. replace trace_ppe_hash with hash value and reduced format string + format_salt = get_format_string(strings, format); + // reduced format string will be added after hash value + write_all_suffix = ",\" "; + write_all_suffix += format; + write_all_suffix += "\""; + + if (!salt.empty()) + { + salt_num = atoi(salt.c_str()); + } + else + { + salt_num = -1; + } + + if (salt_num == -1) + { + salt_num = format_salt; + } + else if (salt_num != format_salt) + { + fprintf(stderr, "ERROR: printf mismatch in '%s': TRACE says %d, format says %d args\n", + line.c_str(), salt_num, format_salt); + } + } + else + { + write_all_suffix = ""; + salt_num = atoi(salt.c_str()); + } + + // get the trex hash value for the strings + get_hash(strings, salt_num, hash32, hash16); + + // check for duplicate and store the mapping + if ((rhash.find(hash32) != rhash.end()) && (rhash[hash32] != strings)) + { + fprintf(stderr, "hash collision: two different strings give the same hash value '%s'\n", hash32.c_str()); + fprintf(stderr, "%s\n%s\n", strings.c_str(), rhash[hash32].c_str()); + return; + } + rhash[hash32] = strings; + + // add the modified line to the output + tmp = prefix; + tmp += "("; + tmp += hashtype; + tmp += " "; + tmp += hash16; + tmp += hashtype_suffix; + tmp += ")"; + tmp += write_all_suffix; + out_line += tmp; + dprintf("changed call: %s...\n", tmp.c_str()); + line = suffix; + } + out_line += line; + if (out_line[out_line.length()-1] != '\n') + out_line += "\n"; +} + +//***************************************************************************** +// main +//***************************************************************************** +int main(int argc, char** argv) +{ + char* p_env = getenv("PPETRACEPPDEBUG"); + if (p_env) + debug = true; + + + int argi = 1; + string arg; + string optarg; + if (argc > 1) arg = argv[1]; + if ((argc < 2) || (arg == "-h")) + { + fprintf(stderr, "usage: %s realcompiler compileroptions -o target source\n", argv[0]); + exit(9); + } + string realcc(argv[argi++]); + string cctype("c++"); + bool optx_found = false; + + if (realcc == "-d") + { + debug = true; + realcc = argv[argi++]; + } + + // wait until -d options is handled before checking $debug + dprintf("ppetracepp version %s - API/macro version %s\n", version.c_str(), macro_version.c_str()); + + p_env = getenv("REALCPP"); + string realcpp; + if (p_env) + realcpp = p_env; + if (realcpp.empty()) + { + dprintf("cannot find cpp, using <realcompiler> -E\n"); + realcpp = realcc; + realcpp += " -E"; + } + dprintf("realcpp is %s\n", realcpp.c_str()); + +//------------------------------------------------------------------------------ +// parse all the arguments +//------------------------------------------------------------------------------ +string source; +string object; +vector<string> ccopts; +vector<string> cppopts; +bool dodeps = false; +string depfile; +string pfx; +string sfx; +int origargi = argi; +for( ; argi < argc; ++argi) +{ + arg = argv[argi]; + dprintf("Processing argv[%d]: \"%s\"\n", argi, arg.c_str()); + if (arg.length() > 2) + { + pfx = arg.substr(0,2); + sfx = arg.substr(arg.length()-2); + } + else + { + pfx = arg; + sfx = arg; + } + dprintf(" pfx: \"%s\" sfx: \"%s\"\n", pfx.c_str(), sfx.c_str()); + + if (pfx == "-o") + { + if (! object.empty()) + { + fprintf(stderr, "two -o options, aborting\n"); + exit(1); + } + if (arg.length() > 2) + { + object = sfx; + } + else + { + object = argv[++argi]; + } + dprintf("object is now %s\n", object.c_str()); + } + else if (arg == "-c") + { + // don't call cpp with -c, this is for the compiler + ccopts.push_back(arg); + dprintf("found -c option\n"); + } + else if (pfx == "-l") + { + // cpp doesn't need library arguments + cppopts.push_back(arg); + } + else if (pfx == "-i") + { + // option takes an argument, handle it too + optarg = argv[argi++]; + ccopts.push_back(arg); + ccopts.push_back(optarg); + cppopts.push_back(arg); + cppopts.push_back(optarg); + dprintf("found option '%s %s'\n", arg.c_str(), optarg.c_str()); + } + else if ((arg == "-L") || + (arg == "-I") || + (arg == "-x") || + (arg == "-b") || + (arg == "-B") || + (arg == "-V") || + (arg == "-D") || + (arg == "--param") || + (arg == "-MQ") || + (arg == "-MT")) + { + // option takes an argument, handle it too + optarg = argv[argi++]; + ccopts.push_back(arg); + ccopts.push_back(optarg); + cppopts.push_back(arg); + cppopts.push_back(optarg); + dprintf("found option '%s %s'\n", arg.c_str(), optarg.c_str()); + if (arg == "-x") + { + // option x sets the language - c or c++ + if ((optarg != "c") && (optarg != "c++") && (optarg != "assembler-with-cpp")) + { + fprintf(stderr, "cannot process language '%s', aborting\n", optarg.c_str()); + exit(1); + } + cctype = optarg; + optx_found = true; + } + } + else if ((arg == "-MD")||(arg == "-MG")) + { + // gen deps + dodeps = true; + dprintf("found %s, creating dependencies\n", arg.c_str()); + } + else if (arg == "-MF") + { + // set dependencies file + depfile = argv[argi++]; + dprintf("set dependencies file to '%s'\n", depfile.c_str()); + } + else if (arg[0] == '-') + { + // arg starts with - so it's an option + ccopts.push_back(arg); + cppopts.push_back(arg); + dprintf("found option '%s'\n", arg.c_str()); + } + else if ((sfx == ".a") || + (sfx == ".o")) + { + // an object or archive, ignore this but give it to cc + ccopts.push_back(arg); + dprintf("found object/archive '%s'\n", arg.c_str()); + } + else if ((sfx == ".c") || + (sfx == ".C") || + (sfx == ".S") || + (arg.substr(arg.length()-4) == ".cpp") || + (arg.substr(arg.length()-4) == ".cxx")) + { + // the source file(s). we should only get one + if (!source.empty()) + { + fprintf(stderr, "don't know to handle two source files, aborting\n"); + exit(1); + } + source = arg; + // put the - (for read-from-stdin) where the source file was + // (order is important!) + ccopts.push_back("-"); + dprintf("found source file %s\n", source.c_str()); + } + else if (access(arg.c_str(), F_OK)) + { + // option but not a file, an unknown option? + ccopts.push_back(arg); + cppopts.push_back(arg); + dprintf("found unknown option '%s'\n", arg.c_str()); + } +} + +//------------------------------------------------------------------------------ +// set other parameters based on arguments specified +//------------------------------------------------------------------------------ +if (source.empty()) +{ + // this might be a call to link a program instead of compile a source (or asm source) + dprintf("NOTME: starting as cc '%s ...'\n", realcc.c_str()); + execvp(realcc.c_str(), &(argv[origargi])); + fprintf(stderr, "ERROR: returned from execvp() call to run %s\n", realcc.c_str()); +} +if (object.empty()) +{ + dprintf("no object file given, default to source name\n"); + // gcc builds object name from source name if no -o given, replacing + // suffix with .o. The file is placed in the current directory, + // not in the source directory! + string n; + string d; + string s; + fileparse(source, n, d, s); + if (!n.empty() && !s.empty()) + { + object = n + ".o"; + dprintf("tracpp: guessing object name %s\n", object.c_str()); + dprintf(" from source name %s\n", source.c_str()); + } + else + { + fprintf(stderr, "Unable to determine Source File Name\n"); + exit(1);; + } +} + +// set value of trace hash according to language +// check source file extension if no explicit -x option given +if (!optx_found) +{ + if (realcc.find("g++") != string::npos) + { + dprintf("compiler language: C++ (from compiler name)\n"); + cctype = "c++"; + } + else + { + if (source.substr(source.length()-2) == ".c") + { + dprintf("compiler language: C (from source file extension)\n"); + cctype = "c"; + } + else if (source.substr(source.length()-2) == ".S") + { + dprintf("compiler language: assembly (from source file extension)\n"); + cctype = "assembler-with-cpp"; + } + else + { + dprintf("compiler language: C++ (default)\n"); + cctype = "c++"; + } + } +} +else +{ + dprintf("compiler language: %s (from option '-x')\n", cctype.c_str()); +} + +if (cctype == "c") +{ + hashtype = "(unsigned short)"; + hashtype_suffix = "U"; +} +else if (cctype == "assembler-with-cpp") +{ + hashtype = ""; + hashtype_suffix = ""; +} +else +{ + hashtype = "(trace_hash_val)"; + hashtype_suffix = "U"; +} +// define TRAC_PPETRACEPP for macros +tmp = "-DTRAC_PPETRACEPP -DTRAC_PPVER="; +tmp += macro_version; +cppopts.push_back(tmp); +if (dodeps) +{ + if (depfile.empty()) + { + if ((p_env = getenv("DEPENDENCIES_OUTPUT")) != NULL) + { + depfile = p_env; + } + else if ((p_env = getenv("SUNPRO_DEPENDENCIES")) != NULL) + { + depfile = p_env; + } + else + { + depfile = object; + if (depfile.substr(depfile.length()-2) == ".o") + { + depfile = depfile.substr(0, depfile.length()-2); + depfile += ".d"; + } + } + } + tmp = "-MD -MF "; + tmp += depfile; + cppopts.push_back(tmp); +} + +//------------------------------------------------------------------------------ +// start cpp +//------------------------------------------------------------------------------ +cmd = realcpp; +for(vector<string>::iterator p = cppopts.begin(); p != cppopts.end(); ++p) +{ + cmd += " "; + cmd += *p; +} +cmd += " "; +cmd += source; +cmd += " -o-"; +dprintf("starting as cpp '%s'\n", cmd.c_str()); +CPP = popen(cmd.c_str(), "r"); +if (CPP == NULL) +{ + fprintf(stderr, "cannot start cpp '%s'\n", realcpp.c_str()); + perror(""); + exit(1); +} + +//------------------------------------------------------------------------------ +// start cc. manually set language as source file extension not available to cc +//------------------------------------------------------------------------------ +string type_str = ""; +if (!optx_found) +{ + // no option -x given by caller, set manually + type_str = "-x "; + type_str += cctype; +} +cmd = realcc; +cmd += " "; +cmd += type_str; +for(vector<string>::iterator p = ccopts.begin(); p != ccopts.end(); ++p) +{ + cmd += " "; + cmd += *p; +} +cmd += " -o "; +cmd += object; +dprintf("starting as cc '%s'\n", cmd.c_str()); +CC = popen(cmd.c_str(), "w"); +if (CC == NULL) +{ + fprintf(stderr, "cannot start cc '%s'\n", realcc.c_str()); + perror(""); + exit(1); +} + +string modifiedfile; +string unmodifiedfile; +if (debug) +{ + modifiedfile = object + ".debug"; + DEBUG = fopen(modifiedfile.c_str(), "w"); + if (DEBUG == NULL) + { + string msg = "cannot open file "; + msg += modifiedfile; + perror(msg.c_str()); + modifiedfile = ""; + } + else + { + fprintf(stderr, "writing preprocessed source to %s\n", modifiedfile.c_str()); + } + unmodifiedfile = object + ".debug_in"; + DEBUGIN = fopen(unmodifiedfile.c_str(), "w"); + if (DEBUGIN == NULL) + { + string msg = "cannot open file "; + msg += unmodifiedfile; + perror(msg.c_str()); + unmodifiedfile = ""; + } + else + { + fprintf(stderr, "writing unprocessed source to %s\n", unmodifiedfile.c_str()); + } +} + +string oldline; +string newline; +static const int MAX_BUFFER = 51200; +char buf[MAX_BUFFER]; +while (!feof(CPP)) +{ + if (fgets(buf, MAX_BUFFER, CPP) != NULL) + { + oldline = buf; + if (DEBUGIN) { fprintf(DEBUGIN, "%s", oldline.c_str()); } + parse_line(hashtab, oldline, newline); + //#print "oldline = $oldline"; + //#print "newline = $newline"; + if (newline.empty()) + { + fprintf(stderr, "hash error in/with file %s\n", source.c_str()); + exit(1); + } + //#print "newline = $newline\n"; + fprintf(CC, "%s", newline.c_str()); + if (DEBUG) { fprintf(DEBUG, "%s", newline.c_str()); } + } +} +if (DEBUG) { fclose(DEBUG); } +if (DEBUGIN) { fclose(DEBUGIN); } +int cmd_rc = pclose(CPP); +if (cmd_rc) +{ + fprintf(stderr, "error from cpp\n"); + if (cmd_rc & 127) + { + fprintf(stderr, "cpp got signal %d\n", (cmd_rc & 127)); + exit(1); + } + else if (cmd_rc >> 8) + { + fprintf(stderr, "cpp returned %d\n", (cmd_rc >> 8)); + exit(cmd_rc >> 8); + } +} +cmd_rc = pclose(CC); +if (cmd_rc) +{ + fprintf(stderr, "error from cc\n"); + if (cmd_rc & 127) + { + fprintf(stderr, "cc got signal %d\n", (cmd_rc & 127)); + exit(1); + } + else if (cmd_rc >> 8) + { + fprintf(stderr, "cc returned %d\n", (cmd_rc >> 8)); + exit(cmd_rc >> 8); + } +} + +if (!hashtab.empty()) +{ + string stringfile = object; + stringfile += ".ppe.hash"; + // open trace string file + FILE* TRC = fopen(stringfile.c_str(), "w"); + if (TRC == NULL) + { + fprintf(stderr, "cannot write trace string file '%s'\n", stringfile.c_str()); + exit(1); + } + dprintf("Writing to file %s\n", stringfile.c_str()); + + string pwd; + FILE* PWD = popen("pwd", "r"); + fgets(buf, MAX_BUFFER, PWD); + pwd = buf; + pclose(PWD); + time_t tt = time(NULL); + sprintf(buf, "%s", asctime(localtime(&tt))); + buf[strlen(buf)-1] = '\0'; // chop off extra newline + fprintf(TRC, "#FSP_TRACE_v2|||%s|||BUILD:%s", buf, pwd.c_str()); + + string srch_str = "||"; + srch_str += source; + int srch_str_len = srch_str.length(); + size_t pos; + for(map<string,string>::iterator p = hashtab.begin(); p != hashtab.end(); ++p) + { + pos = (p->second).find(srch_str); + if ((pos != string::npos) && ((pos + srch_str_len) == (p->second).length())) + { + // source file name is already part of the string + fprintf(TRC, "%s||%s\n", (p->first).c_str(), (p->second).c_str()); + } + else + { + fprintf(TRC, "%s||%s||%s\n", (p->first).c_str(), (p->second).c_str(), source.c_str()); + } + //#print TRC "$key||$source||$hashtab{$key}\n"; + } + fclose(TRC); +} +else +{ + dprintf("No trace calls/strings found, not writing hash file\n"); +} +} // end main diff --git a/src/ppe/tools/ppetracepp/trac_interface.h b/src/ppe/tools/ppetracepp/trac_interface.h new file mode 100755 index 0000000..27215fc --- /dev/null +++ b/src/ppe/tools/ppetracepp/trac_interface.h @@ -0,0 +1,370 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/tools/ppetracepp/trac_interface.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/****************************************************************************** +// @file trac_interface.h +// @brief Interface codes for TRAC component. +*/ +/****************************************************************************** + * + * @page ChangeLogs Change Logs + * @section _trac_interface_h trac_interface.h + * @verbatim + * + * Flag Def/Fea Userid Date Description + * ------- ---------- -------- ---------- ---------------------------------- + * TEAM 06/16/2010 Port + * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments + * @pb00E pbavari 03/11/2012 Added correct include file + * @at009 859308 alvinwan 10/15/2012 Added tracepp support + * @ai005 860268 ailutsar 11/20/2012 Create trace test applet + * @rc005 864101 rickylie 12/12/2012 add small circ buffer to handle ISR semaphore conflict + * + * @endverbatim + * + *///*************************************************************************/ + +#ifndef _TRAC_INTERFACE_H +#define _TRAC_INTERFACE_H + +/** \defgroup Trace Trace Component + * Port of the trace code used in the fsp and tpmd. + */ + +//************************************************************************* +// Includes +//************************************************************************* + +//************************************************************************* +// Externs +//************************************************************************* + +//************************************************************************* +// Macros +//************************************************************************* +/** + * \defgroup TracMacros Trace Component Macro Interfaces + * \ingroup Trace + * Used to trace 0 - 5 arguments or a binary buffer when using a hash value. + */ +/*@{*/ + + +// @at009c - start +#define TRACE(i_td,i_string,args...) \ + trace_adal_write_all(i_td,trace_adal_hash(i_string,-1),__LINE__,0,##args) + +#define TRACEBIN(i_td,i_string,i_ptr,i_size) \ + trac_write_bin(i_td,trace_adal_hash(i_string,0),__LINE__,i_ptr,i_size) + +#ifndef NO_TRAC_STRINGS + +#define FIELD(a) \ + printf("%s",a) + +#define FIELD1(a,b) \ + printf("%s%lx",a,(unsigned long)b) + +#else // NO_TRAC_STRINGS + +#define FIELD(a) + +#define FIELD1(a,b) + +#endif // NO_TRAC_STRINGS + +#define SUCCESS 0 +// @at009c - end + + + +/*@}*/ + +//************************************************************************* +// Defines/Enums +//************************************************************************* +#define TRACE_MAX_ARGS 5 /*!< Maximum number of args to trace */ + +typedef uint32_t trace_hash_val; + +// NOTE! Increment this when new components are added! +#define TRAC_NUM_TRACE_COMPONENTS 1 + + +#define TRACE_BUFFER_SIZE 8192 // @ai005a + +#define CIRCULAR_BUFFER_SIZE 4 // @rc005a + +typedef uint32_t UINT32; +typedef int32_t INT32; +typedef uint8_t UCHAR; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef char CHAR; +typedef unsigned int UINT; +typedef unsigned long ULONG; +typedef int INT; +typedef void VOID; + +//************************************************************************* +// Structures +//************************************************************************* +/* + * @brief Structure is put at beginning of all trace buffers + */ +typedef struct trace_buf_head { + UCHAR ver; /*!< version of this struct (1) */ + UCHAR hdr_len; /*!< size of this struct in bytes */ + UCHAR time_flg; /*!< meaning of timestamp entry field */ + UCHAR endian_flg; /*!< flag for big ('B') or little ('L') endian */ + CHAR comp[16]; /*!< the buffer name as specified in init call */ + UINT32 size; /*!< size of buffer, including this struct */ + UINT32 times_wrap; /*!< how often the buffer wrapped */ + UINT32 next_free; /*!< offset of the byte behind the latest entry */ + UINT32 te_count; /*!< Updated each time a trace is done */ + UINT32 extracted; /*!< Not currently used */ +}trace_buf_head_t; + +/*! + * @brief Timestamp and thread id for each trace entry. + */ +typedef struct trace_entry_stamp { + UINT32 tbh; /*!< timestamp upper part */ + UINT32 tbl; /*!< timestamp lower part */ + UINT32 tid; /*!< process/thread id */ +}trace_entry_stamp_t; + +/* + * @brief Structure is used by adal app. layer to fill in trace info. + */ +typedef struct trace_entry_head { + UINT16 length; /*!< size of trace entry */ + UINT16 tag; /*!< type of entry: xTRACE xDUMP, (un)packed */ + UINT32 hash; /*!< a value for the (format) string */ + UINT32 line; /*!< source file line number of trace call */ +}trace_entry_head_t; + +/* + * @brief Parameter traces can be all contained in one write. + */ +typedef struct trace_entire_entry { + trace_entry_stamp_t stamp; + trace_entry_head_t head; + UINT32 args[TRACE_MAX_ARGS + 1]; +} trace_entire_entry_t; + + +/* + * @brief Binary first writes header and time stamp. + */ +typedef struct trace_bin_entry { + trace_entry_stamp_t stamp; + trace_entry_head_t head; +} trace_bin_entry_t; + +/** + * @brief Used as input to traces to get to correct buffer. + */ +typedef trace_buf_head_t * tracDesc_t; + +/* + * @brief Structure is used to hold array of all trace descriptors + */ +typedef struct trace_descriptor_array +{ + tracDesc_t *entry; /*!< Pointer to trace descriptor */ + CHAR *comp; /*!< Pointer to component name */ +}trace_descriptor_array_t; + +// @rc005a - start +typedef struct circular_buf_head +{ + UINT32 head; // pointer to head + UINT32 tail; // pointer to tail + UINT32 entryCount; // nums of entry +} circular_buf_header_t; + + +typedef struct circular_entire_data { + UINT32 len; + CHAR comp[4]; + trace_entire_entry_t entry; +} circular_entire_data_t; + +// @rc005a - end + +//************************************************************************* +// Globals +//************************************************************************* +// All TPMF component trace descriptors. +extern tracDesc_t g_trac_inf; // @at009a +extern tracDesc_t g_trac_err; // @at009a +extern tracDesc_t g_trac_imp; // @at009a + +extern const trace_descriptor_array_t g_des_array[]; + +//************************************************************************* +// Function Prototypes +//************************************************************************* + +/** + * \defgroup TracIntefaces Trace Component Interfaces for External Use + * \ingroup Trace + */ +/*@{*/ + + +/** + * @brief Allocate and initialize all trace buffers in memory. + * + * This function will allocate memory for each of the pre-defined trace + * buffers, initilize the buffers with starting data, and setup the + * trace descriptors which each component will use to trace. + * + * This function must be called first before any components try to trace! + * + * @return Non-zero return code on error. + */ +UINT TRAC_init_buffers(void); + +/** + * @brief Retrieve full trace buffer for component i_comp + * + * This function assumes memory has already been allocated for + * the full trace buffer in o_data. + * + * @param i_td_ptr Trace descriptor of buffer to retrieve. + * @param o_data Pre-allocated pointer to where data will be stored. + * + * @return Non-zero return code on error + */ +UINT TRAC_get_buffer(const tracDesc_t i_td_ptr, + void *o_data); + +/** + * @brief Retrieve partial trace buffer for component i_comp + * + * This function assumes memory has already been allocated for + * the trace buffer (size io_size). This function will copy + * in up to io_size in bytes to the buffer and set io_size + * to the exact size that is copied in. + * + * @param i_td_ptr Trace descriptor of buffer to retrieve. + * @param o_data Pre-allocated pointer to where data will be stored. + * @param io_size Size of trace data to retrieve (input) + * Actual size of trace data stored (output) + * + * @return Non-zero return code on error + */ +UINT TRAC_get_buffer_partial(const tracDesc_t i_td_ptr, + void *o_data, + UINT *io_size); + +/** + * @brief Retrieve trace descriptor for input component name + * + * @param i_comp Component name to retrieve trace descriptor for. + * + * @return Valid trace descriptor on success, NULL on failure. + */ +tracDesc_t TRAC_get_td(const char *i_comp); + +/** + * @brief Reset all trace buffers + * + * @return Non-zero return code on error + */ +UINT TRAC_reset_buf(void); + +/*@}*/ // Ending tag for external interface module in doxygen + + +/** + * @brief Trace input integers to trace buffer. + * + * This function assumes i_td has been initialized. + * + * @param io_td Intialized trace descriptor point to buffer to trace to. + * @param i_hash Hash value to be recorded for this trace. + * @param i_fmt Output format + * @param i_line Line number trace is occurring on. + * @param i_type trace type. filed or debug. + * @param ... parames that are limited to a size of 4 bytes, i.e. int, uint32_t, nnn* + * + * @return Non-zero return code on error. + */ +UINT trace_adal_write_all(tracDesc_t io_td,const trace_hash_val i_hash, + const char *i_fmt,const ULONG i_line, const ULONG i_type,...); + + +/** + * @brief Trace input integers to trace buffer. + * + * This function assumes i_td has been initialized. + * + * @param io_td Intialized trace descriptor point to buffer to trace to. + * @param i_hash Hash value to be recorded for this trace. + * @param i_line Line number trace is occurring on. + * @param i_num_args Number of arguments to trace. + * @param i_1 Input Parameter 1 + * @param i_2 Input Parameter 2 + * @param i_3 Input Parameter 3 + * @param i_4 Input Parameter 4 + * @param i_5 Input Parameter 5 + * + * @return Non-zero return code on error. + */ +UINT trac_write_int(tracDesc_t io_td,const trace_hash_val i_hash, + const ULONG i_line, + const UINT i_num_args, + const ULONG i_1,const ULONG i_2,const ULONG i_3, + const ULONG i_4,const ULONG i_5 + ); + + + /** + * @brief Trace binary data to buffer. + * + * This function assumes i_td has been initialized. + * + * @param io_td Intialized trace descriptor point to buffer to trace to. + * @param i_hash Hash value to be recorded for this trace. + * @param i_line Line number trace is occurring on. + * @param i_ptr Pointer to binary data to trace. + * @param i_size Size of data to copy from i_ptr. + * + * @return Non-zero return code on error. + */ +UINT trac_write_bin(tracDesc_t io_td,const trace_hash_val i_hash, + const ULONG i_line, + const void *i_ptr, + const ULONG i_size); + +//************************************************************************* +// Functions +//************************************************************************* + +#endif //_TRAC_INTERFACE_H diff --git a/src/ppe/tools/ppetracepp/tracehash.pl b/src/ppe/tools/ppetracepp/tracehash.pl new file mode 100755 index 0000000..fa24490 --- /dev/null +++ b/src/ppe/tools/ppetracepp/tracehash.pl @@ -0,0 +1,897 @@ +#!/usr/bin/perl -w +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/ppe/tools/ppetracepp/tracehash.pl $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 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 +# File tracehash.pl created by B J Zander. + +use strict; + +sub determine_args(); +sub launch_cpp_and_parse($$); +sub cpp_dir($); +sub read_string_file(); +sub collect_files($); +sub assimilate_file($); +sub hash_strings(); +sub write_string_file(); +sub help(); + +select (STDERR); +$| = 1; # Make all prints to STDERR flush the buffer immediately +select (STDOUT); +$| = 1; # Make all prints to STDOUT flush the buffer immediately + +# Constants +my $HEAD_SEP = "|||"; +my $HEAD_EYE_CATCHER = "#FSP_TRACE_v"; +my $HEAD_BUILD_FLAG = "BUILD:"; +my $HEAD_VER_FLAG = 2; +my $BB_STRING_FILE = "/opt/fsp/etc/BB_StringFile"; + +# Global Variables +my $debug = 0; +my $seperator = "&&&&"; +my $file_name = "trexStringFile"; +my $in_sand; +my ($backing) = $ENV{'bb'}; +my $hash_prog = "trexhash"; #default to in path +my $build = ""; +my ($sandbox) = $ENV{'SANDBOX'} || ""; +my ($context) = $ENV{'CONTEXT'} || ""; +my ($sandboxbase) = $ENV{'SANDBOXBASE'} || ""; +my ($bb); +my ($sourcebase) = "$sandboxbase/src"; +my ($version) = $HEAD_VER_FLAG; # default to oldest version +my ($collect) = 0; +my ($INCLUDE, $Arg, $file, $dir, $string_file); +my $args = ""; + +my $fail_on_collision = 0; # 1 = exit with error if hash collision occurs +my $hash_filename_too = 0; # 1 = hash is calculated over format string + filename + +print "sourcebase = $sourcebase\n" if $debug; +print "sandbox = $sandbox\n" if $debug; +print "backing = $backing\n" if $debug; +print "context = $context\n" if $debug; + +if ($context =~ /x86/) +{ + $bb = "i586-pc-linux-gnu"; +} +else +{ + $bb = "powerpc-linux"; +} + +if(($sourcebase =~ /\w+/) && ($sandbox =~ /\w+/)) +{ + $INCLUDE = "-I $sandboxbase/export/$context/fips/include -I $backing/export/$context/fips/include -I /opt/fsp/$bb/include/fsp -I/opt/fsp/$bb/include/ -include /opt/fsp/$bb/include/fsp/tracinterface.H"; +} +else +{ + print "Not in Sandbox so guessing Include Paths...\n" if $debug; + $INCLUDE = "-I/opt/fsp/i586-pc-linux-gnu/include/fsp -I/opt/fsp/i586-pc-linux-gnu/include/ -include /opt/fsp/i586-pc-linux-gnu/include/fsp/tracinterface.H"; +} + +# I/P Series work in ODE sandbox env. +if ($sandboxbase =~ /\w+/) +{ + $in_sand = 1; + print "backing = $backing\n" if $debug; +} +else +{ + $in_sand = 0; +} + + + +# Parse the input parameters. + +while (@ARGV) { + $Arg = shift; + + if ($Arg eq "-h" || $Arg eq "-H") { + help(); + exit(127); + } + if ($Arg eq "-f") { + $file = shift; + next; + } + if ($Arg eq "-d") { + $dir = shift; + next; + } + if ($Arg eq "-s") { + $string_file = shift; + next; + } + if ($Arg eq "-c") { + $collect = 1; + next; + } + if ($Arg eq "-v") { + $debug = 1; + print "debug on\n" if $debug; + next; + } + if ($Arg eq "-C") { # fail if a hash collision is detected + $fail_on_collision = 1; + next; + } + if ($Arg eq "-F") { # hash is calculated over format string + file name + $hash_filename_too = 1; + next; + } + if ($Arg eq "-S") { + $BB_STRING_FILE = ""; + next; + } + + #just pass it onto compiler + $args = $args . " " . $Arg; +} + +print "args = $args\n" if $debug; + +if (!$file && !$dir && !$in_sand) { + help(); + exit(127); +} + +################################# +# M A I N # +################################# + +my $clock = `date`; + +$build = $HEAD_EYE_CATCHER . "$HEAD_VER_FLAG" . $HEAD_SEP . $clock . $HEAD_SEP . $HEAD_BUILD_FLAG; + +$build =~ s/\n//g; + +# Global array to hold the parsed TRAC macro calls. +my @strings = (); + +# Assoc. arrays to hold hash|string values. +my %string_file_array = (); +my %hash_strings_array = (); + +# Check all provided arguments and look for defaults if not provided by user +determine_args(); + +# Scan the appropriate files or directories for TRAC macro calls. + +if (defined $dir) +{ + + $build = $build . $dir; # default to put at top of string file + if($collect) + { + collect_files($dir); + } + else + { + cpp_dir($dir); + # Hash the string that have been scanned. + %hash_strings_array = hash_strings(); + } +} +else +{ + $build = $build . $file; # default to put at top of string file + + if($collect) + { + assimilate_file($file); + } + else + { + # make sure include path includes directory that file is in + if($file =~ /^(.+)\/[^\/]+\.C$/) + { + + launch_cpp_and_parse($file,$1); + } + else + { + # No path in front of file so it has to be local dir + launch_cpp_and_parse($file,"./"); + } + # Hash the string that have been scanned. + %hash_strings_array = hash_strings(); + } +} + +# Read the existing string file into memory. +%string_file_array = read_string_file(); + +# Write out the new string file. check for collisions of new/old string here +write_string_file(); + +print "Hashing Started at $clock\n"; +$clock = `date`; +print "Hashing Finished at $clock\n"; + +exit 0; + + +################################# +# S U B R O U T I N E S # +################################# + +#============================================================================= +# Enhance usability by figuring out which build env. we are in +#============================================================================= +sub determine_args() { + + + # Find trexhash program + # but only if needed (i.e. not in collect mode) + if (!$collect) { + my $tmp = `which $hash_prog`; + chomp $tmp; + + if ($tmp eq '') { + print STDOUT "\nWarning: Program trexhash does not exist in path.\n" if $debug; + $hash_prog = "./trexhash"; + + $tmp = `which $hash_prog`; + chomp $tmp; + if ($tmp eq '') { + print STDOUT "\nError: Unable to find trexhash \n"; + exit(127); + } + } + } + + # Verify input values. + if ((!defined $file) && (!defined $dir)) { + if(!($in_sand)) + { + print STDOUT "\nError: No input directory or file provided as input to scan\n"; + exit(127); + } + + # Assume they want sandbox scanned + if($collect) + { + # collect all string files generated by tracepp and merge + $dir = "$sandboxbase/obj/"; + } + else + { + # generate our own string file by pre-compiling all source code + $dir = "$sandboxbase/src/"; + } + print STDOUT "\n-f <file> or -d <dir> not found...scanning $dir by default\n\n"; + } + + if (!defined $string_file) + { + if ($in_sand) + { + + # Copy the current string file from backing build into our sandbox + system ("cp $backing/obj/$file_name $sandboxbase/obj/$file_name") + if !(-e "$sandboxbase/obj/$file_name"); + + $string_file = "$sandboxbase/obj/$file_name"; + } + else + { + $string_file = "./$file_name"; + } + print STDOUT "-sf <string_file> not specified, using $string_file instead...\n\n" if $debug; + + } + + # Try Creating the string file + `touch $string_file`; + + if (! -f $string_file) { + print STDOUT "\nError: File $string_file does not exist. Current directory may not be writable.\n\n"; + help(); + exit(127); + } + + # Make sure trexStringFile is readable/writeable + system("chmod ugo+rw $string_file"); + +} + +#============================================================================= +# Launch cpp script and grab input from it looking for trace calls. +#============================================================================= +sub launch_cpp_and_parse($$) { + + my ($l_loc, $l_dir) = @_; + + print "Processing file $l_loc\n" if $debug; + my $cmd = "/usr/bin/cpp $INCLUDE -I $l_dir $args $l_loc|"; + print "$cmd\n" if $debug; + open(FH,"$cmd") + or die ("Cannot open $_:$!,stopped"); + + # Read through all lines in the file.. + my $line = <FH>; + while (defined $line) + { + chop $line; # remove EOL + $line =~ s/^\s*//; # remove unneccesary beginning white space. + $line =~ s/\s*$//; # remove unneccesary ending white space. + # Look for lines that are trace macro calls. + #if (/(trace_adal_hash)(\()( *)(".+")(,)(\d)/) + #if ($line =~ /(.*?)(trace_adal_hash)(\()( *)(".+")(,)(\d)\)+(.*\d.*)/) + while($line =~ m/^(.*?)trace_adal_hash\s*\(\s*(("[^"]*"\s*)+),\s*(\d+)\s*\)(.*)$/) + { + my ($prefix, $strings, $salt, $suffix) = ($1, $2, $4, $5); + print STDOUT "$strings $salt\n" if $debug; + $strings =~ s/"\s*$//; # remove trailing " and space + $strings =~ s/^"//; # remove leading " + $strings =~ s/"\s*"//g; + # Check to see if it's contained on a single line, or if we + # have to combine lines to get a complete trace call. + + # Save the macro call so it can be hashed later.. + push (@strings, [$l_loc, $strings, $salt]); + $line = $suffix; # check rest of line for a second trace call + } + my $nextline = <FH>; + last if !defined $nextline; + # if a trace call is spread over multiple lines we have to add the next + # line from the source. the only problem is the definition/declaration + # of trace_adal_hash: we have to ignore that. we catch that by requiring + # a " after the function name. hopefully nobody writes a comment with + # a " after the function declaration ... + if ($line =~ /trace_adal_hash.*"/) { + $line .= $nextline; + } else { + $line = $nextline; + } + } + close(FH); +} + +#============================================================================= +# run cpp on all files in this directory and return the output +#============================================================================= +sub cpp_dir($) { + + my ($l_dir) = @_; + my @dir_entry; + my $l_entry; + + # Open the directory and read all entry names. + opendir ( DH , "$l_dir") + or die ("Cannot open $l_dir: $!, stopped"); + + print STDOUT "Processing directory $l_dir\n" if $debug; + @dir_entry = readdir(DH); + closedir(DH); + + while (@dir_entry) { + $l_entry = shift(@dir_entry); + + if ($l_dir =~ m"/$") { + $l_entry = "$l_dir$l_entry"; + } + else { + $l_entry = "$l_dir/$l_entry"; + } + + # Is the entry a directory? + if (-d $l_entry) { + + if($l_entry =~ m"/?([^/]+)$") + { + # check dir we are going into + print "dir = $1\n" if $debug; + # should we recurse into this directory. + if ($1 =~ m/^(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + cpp_dir($l_entry); + } + else + { + # unable to determine name of dir (no / in filename) + # should we recurse into this directory. + if ($l_entry =~ m/^(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + cpp_dir($l_entry); + } + } + # Is the entry a file? + elsif ((-f $l_entry) && ($l_entry =~ m/\.C$/)) { + # it's a file so + launch_cpp_and_parse($l_entry,$l_dir); + } + else { + # Not a file or directory so ignore it... + } + } +} + +#============================================================================= +# Read in strings from the existing trace string file.... +#============================================================================= +sub read_string_file() { + + my %o_strings; + my ($line) = ""; + my ($l_hash) = ""; + my ($l_str) = ""; + my ($cur_build) = ""; + my ($l_file) = ""; + + + # Make sure we can open each file. + open ( FH , "<$string_file") + or die ("Cannot open $_: $!, stopped"); + + $line = <FH>; + + print "first line in trexStringFile= $line\n" if $debug; + + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + + print "version = $version\n" if $debug; + + #Always put latest version in file + $line =~ s/^$HEAD_EYE_CATCHER\d/${HEAD_EYE_CATCHER}${HEAD_VER_FLAG}/; + + # Take previous version in file and use it. + $build = $line; + chomp($build); + $line = <FH>; + + while (defined $line) { + chomp $line; # remove EOL + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + else + { + print "Unknown version of stringfile $version\n"; + exit(127); + } + $o_strings{$l_hash} = $l_str . "||" . $l_file; + $line = <FH>; + } + + } + else + { # If there is a file then we are dealing with the first + # version of trexStringFile so don't look for file name. + if ($debug) { + print "version 0 stringfile detected: $string_file\n"; + } + + # there is a file and it doesn't have a header + $version = 0; + + while (defined $line) { + chomp $line; # remove EOL + ($l_hash,$l_str) = split(/\|\|/, $line); + $o_strings{$l_hash} =$l_str . "||" . "NO FILE"; + $line = <FH>; + } + } + + close(FH); + + #Time to look for a building block string file + if($BB_STRING_FILE ne "" and $string_file ne $BB_STRING_FILE and -f $BB_STRING_FILE) + { + + # Make sure we can open the file. + open ( FH , "<$BB_STRING_FILE") + or die ("Cannot open $_: $!, stopped"); + + $line = <FH>; + + print "first line in BB_StringFile = $line\n" if $debug; + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + + $line = <FH>; + while (defined $line) + { + chop $line; # remove EOL + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + #($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + $o_strings{$l_hash} = $l_str . "||" . $l_file ; + $line = <FH>; + } + } + else + { + print "*** ERROR: BB_StringFile '$BB_STRING_FILE' should always have version!!!\n" + } + + } + else + { + print "$BB_STRING_FILE is not available\n" if $debug; + } + #All files are latest version now. + $version = $HEAD_VER_FLAG; + return %o_strings; +} + +#============================================================================= +# Read in strings from the existing trace string file.... +#============================================================================= +sub collect_files($) { + + my ($l_dir) = @_; + my (@dir_entry); + my ($l_entry) = ""; + + # Open the directory and read all entry names. + opendir ( DH , "$l_dir") + or die ("Cannot open $l_dir: $!, stopped"); + + print STDOUT "Processing directory $l_dir\n" if $debug; + @dir_entry = readdir(DH); + closedir(DH); + + while (@dir_entry) { + $l_entry = shift(@dir_entry); + + if ($l_dir =~ m"/$") { + $l_entry = "$l_dir$l_entry"; + } + else { + $l_entry = "$l_dir/$l_entry"; + } + + # Is the entry a directory? + if (-d $l_entry) { + + # should we recurse into this directory. + if ($l_entry =~ m/\/(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + collect_files($l_entry); + } + # Is the entry a file? + elsif ((-f $l_entry) && ($l_entry =~ m"\.hash$")) { + # it's a file so + assimilate_file($l_entry); + } + else { + # Not a file or directory so ignore it... + } + } + +} + +#============================================================================= +# Read in data from file and add to master one +#============================================================================= +sub assimilate_file($) { + + my ($l_loc) = @_; + + my (%o_strings); + my ($line) = ""; + my ($l_hash) = ""; + my ($l_str) = ""; + my ($l_file) = ""; + + # Make sure we can open each file. + open ( FH , "<$l_loc") + or die ("Cannot open $_: $!, stopped"); + + $line = <FH>; + + print "Assimilate: first line in $l_loc = $line" if $debug; + + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + if ($version eq "1") { + if ($hash_filename_too) { + print "*** ERROR: hash_filename_too (-F) isn't possible with trace version 1\n"; + print " please rebuild all .hash files and global trexStringFile\n"; + print " version 1 file is '$l_loc'\n"; + exit(127); + } + } elsif ($version ne "2") { + print "Unknown version of stringfile $version\n"; + exit(127); + } + + $line = <FH>; + + + while (defined $line) { + chop $line; # remove EOL + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + my $newstring = $l_str . "||" . $l_file; + if (exists $hash_strings_array{$l_hash}) { + my $hashstr1 = $hash_strings_array{$l_hash}; + my $hashstr2 = $newstring; + if (!$hash_filename_too) { + # hash was made over format string only, remove file name + $hashstr1 =~ s/\|\|.*$//; + $hashstr2 = $l_str; + } + if ($debug) { + print "a_f: compare $hashstr1\n", + " vs. $hashstr2\n"; + } + if ($hashstr1 ne $hashstr2) + { + print "*** ERROR: HASH Collision! (a_f)\n", + " Two different strings have the same hash value ($l_hash)\n", + " String 1: $hash_strings_array{$l_hash}\n", + " String 2: $newstring\n"; + if ($fail_on_collision) { + exit(1); + } + } + } + $hash_strings_array{$l_hash} = $newstring; + $line = <FH>; + } + + } + else + { # If there is a file then we are dealing with the first + # version of trexStringFile so don't look for file name. + # these files shouldn't be there anymore. we don't check for collisions here + if ($debug) { + print "version 0 stringfile detected: $string_file\n"; + } + + if(defined $line) + { + # there is a file and it doesn't have a header + $version = 0; + } + + while (defined $line) { + chop $line; # remove EOL + ($l_hash,$l_str) = split(/\|\|/, $line); + $hash_strings_array{$l_hash} = $l_str . "||" . "NO FILE"; + $line = <FH>; + } + } + $version = $HEAD_VER_FLAG; + close(FH); +} + +#============================================================================= + +#============================================================================= +sub hash_strings() { + + my ($hash_val, $l_key, $l_hash, %l_hash_strings); + my ($line_feed) = chr(10); + my ($l_file_name) = "NO FILENAME"; + print "\nHashing printf strings.\n\n"; + + foreach my $str (@strings) { + my $printf_string; + $l_file_name = $str->[0]; + $printf_string = $str->[1]; + $l_key = $str->[2]; + print "printf_string = $printf_string\n" if $debug; + $printf_string =~ s/"\s?"//g; #multi line traces will have extra " in them + $printf_string =~ s/`/\\`/g; # excape ' + $printf_string =~ s/\\n/$line_feed/g; # escape \n + if ($hash_filename_too) { + $printf_string .= "||" . $l_file_name; + } + + # call the hasher. + print "$hash_prog \"$printf_string\" $l_key\n" if $debug; + $hash_val = `$hash_prog \"$printf_string\" $l_key`; + if ($?) { + my ($hp_ret, $hp_sig) = ($? >> 8, $? & 127); + if ($hp_sig) { + print "*** ERROR: $hash_prog died with signal $hp_sig\n"; + } elsif ($hp_ret) { + print "*** ERROR: $hash_prog returned the error $hp_ret\n"; + if ($hash_val) { + print " error from $hash_prog:\n$hash_val"; + } + } + exit(1); + } + print "printf_string = $printf_string l_key = $l_key hash val = $hash_val\n" if $debug; + + # undo escaping + $printf_string =~ s/$line_feed/\\n/g; + $printf_string =~ s/\\`/`/g; + + if (exists $l_hash_strings{$hash_val}) + { + # hash val was found before. check if it's the same string + # else we have a hash collision + my $l_tmp = $l_hash_strings{$hash_val}; + if (!$hash_filename_too) { + $l_tmp =~ s/\|\|.*$//; + } + if ($l_tmp ne $printf_string) + { + print "*** ERROR: HASH Collision! (h_s)\n", + " Two different strings have the same hash value ($hash_val)\n", + " String 1: $l_hash_strings{$hash_val}\n", + " String 2: $printf_string (file $l_file_name)\n"; + if ($fail_on_collision) { + exit(1); + } + } + } + # this will overwrite an old string with a new one if a collision occurred + # but we might want to bail out in this case anyway + $printf_string = $printf_string . "||" . $l_file_name; + $l_hash_strings{$hash_val} = $printf_string; + } + return %l_hash_strings; +} +#============================================================================= + +#============================================================================= +sub write_string_file() { + + my (@keys) = (); + my ($l_key) = ""; + + # Combine the contents of the existing string file with the trace calls + # that we have just hashed. + print STDOUT "\nCombining Hash strings...\n\n"; + + @keys = keys(%hash_strings_array); + + foreach $l_key (@keys) { + my $l_tmp = $hash_strings_array{$l_key}; # freshly collected strings + if (exists $string_file_array{$l_key}) + { # hash exists in list from trexStringFile + my $l_tmp2 = $string_file_array{$l_key}; + if (!$hash_filename_too) { + $l_tmp =~ s/\|\|.*$//; + $l_tmp2 =~ s/\|\|.*$//; + } + + # Check for hash collisions. + if ($l_tmp ne $l_tmp2) + { + print "*** ERROR: HASH Collision! (w_s_f)\n", + " Two different strings have the same hash value ($l_key)\n", + " String 1: $hash_strings_array{$l_key}\n", + " String 2: $string_file_array{$l_key}\n"; + if ($fail_on_collision) { + exit(1); + } + # don't fail, write new one + } + } + if($version > 0) + { + # add/replace the new string to the string_file_array. + $string_file_array{$l_key} = $hash_strings_array{$l_key} + } + else + { + # old version so only write out format string (not file name to) + $string_file_array{$l_key} = $l_tmp; + } + } + + # Write out the updated string file. + print STDOUT "\nWriting updated hash||string file...\n\n"; + + @keys = sort(keys(%string_file_array)); + + open ( FH , ">$string_file") + or die ("Cannot open $_: $!, stopped"); + + if($version > 0) + { + print FH "$build\n"; # only print version if newer then version 0 + } + foreach $l_key (@keys) { + print FH "$l_key||$string_file_array{$l_key}\n"; + } + close FH; +} +#============================================================================= + +#============================================================================= +# Display command invokation help for this program... +#============================================================================= +sub help() { + print << "EOF"; +tracehash.pl - create a trace string file from sources or collect tracepp files +Usage: tracehash.pl [options] + General options: + -h - Print this help text. + -v - Be verbose, tell what's going on (debug output) + Operation modes + -c - Collect StringFiles created by tracepp and merge. + default - Scan source files for trace calls. + +Collect mode: tracehash.pl -c [-vFCS] [-d <dir>] [-s <string_file>] + tracehash.pl -c [-vFCS] [-f <file>] [-s <string_file>] + Collect string files created by tracepp (.hash) from directory tree at + <dir> or read them from string file <file> and write to file + <string_file>, adding entries already in this file. + -f - String file to read and write/add to <string_file>. + -d - Start of directory tree to scan for .hash files. Default = . + -s - File with trace strings (and hashes) to read from and write to + default = ./trexStringFile + -F - hash is calculated over trace string and source file name, + otherwise without source file name + -C - report an error if a hash collisions occurs + -S - don't read global FLD-2.2 string file ($BB_STRING_FILE) + If tracehash.pl is called in a FipS build sandbox without -d and -f + defaults for the sandbox will be used. + +Scan mode: tracehash.pl [-vFCS] [-d <dir>] [-s <string_file>] [ccpopts] + tracehash.pl [-vFCS] [-f <file>] [-s <string_file>] [cppopts] + Scan all files in directory tree <dir> or scan file <file> and write + strings to file <string_file>. Strings already in this file will be merged. + -f - Source file to scan for trace entries. + -d - Source directory to scan for trace entries. + -s - File with trace strings (and hashes) to read from and write to. + default = ./trexStringFile + -F - hash for string was build from format string + source file name + -C - report an error if hash collisions occur + -S - don't read global FLD-2.2 string file ($BB_STRING_FILE) + All other arguments will be passed verbatim to cpp +EOF +} +#============================================================================= + |