From 420e6d248cc6d2b3c39bc3970e3bb6747b3bddc3 Mon Sep 17 00:00:00 2001 From: William Bryan Date: Mon, 3 Aug 2015 12:38:58 -0500 Subject: new ssx and lib files Change-Id: I2328b1e86d59e3788910687d762fb70ec680058f Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/19503 Reviewed-by: William A. Bryan Tested-by: William A. Bryan --- src/occ_405/thread/chom.c | 451 +++++++++++++++++++++++++++++ src/occ_405/thread/chom.h | 231 +++++++++++++++ src/occ_405/thread/test/Makefile | 64 +++++ src/occ_405/thread/test/app.mk | 79 +++++ src/occ_405/thread/test/threadtest.c | 317 +++++++++++++++++++++ src/occ_405/thread/thread.h | 88 ++++++ src/occ_405/thread/threadSch.c | 322 +++++++++++++++++++++ src/occ_405/thread/threadSch.h | 49 ++++ src/occ_405/thread/thread_service_codes.h | 48 ++++ src/occ_405/thread/thrm_thread.c | 459 ++++++++++++++++++++++++++++++ src/occ_405/thread/thrm_thread.h | 62 ++++ 11 files changed, 2170 insertions(+) create mode 100755 src/occ_405/thread/chom.c create mode 100755 src/occ_405/thread/chom.h create mode 100755 src/occ_405/thread/test/Makefile create mode 100755 src/occ_405/thread/test/app.mk create mode 100755 src/occ_405/thread/test/threadtest.c create mode 100755 src/occ_405/thread/thread.h create mode 100755 src/occ_405/thread/threadSch.c create mode 100755 src/occ_405/thread/threadSch.h create mode 100755 src/occ_405/thread/thread_service_codes.h create mode 100755 src/occ_405/thread/thrm_thread.c create mode 100755 src/occ_405/thread/thrm_thread.h (limited to 'src/occ_405/thread') diff --git a/src/occ_405/thread/chom.c b/src/occ_405/thread/chom.c new file mode 100755 index 0000000..b75bda8 --- /dev/null +++ b/src/occ_405/thread/chom.c @@ -0,0 +1,451 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ/thread/chom.c $ */ +/* */ +/* 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 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern amec_sys_t g_amec_sys; + +#define CHOM_SENSOR_DATA(index,data) [index] = data + +// chom timer +uint32_t g_chom_gen_periodic_log_timer; +// track which power mode has been during the polling period +uint8_t g_chom_pwr_modes[OCC_INTERNAL_MODE_MAX_NUM]; // Nominal, SPS, DPS, DPS-MP, FFO +// force immediate chom log flag +uint8_t g_chom_force; +// chom data log +ChomLogData_t g_chom_log; +ChomLogData_t * g_chom = &g_chom_log; + +// Make sure that the size of chom log is less than 3kB +// otherwise cause error on the compile. +STATIC_ASSERT( sizeof(ChomLogData_t) > CHOM_LOG_DATA_MAX ); + +// Chom Sensors Table +// Some of the chom sensors need multiple mini-sensor to calculate +// the max, summstion of temperature or bandwidth +// mark those mini-sensor "NULL" and will be updated +// from "chom_update_sensors()" + +const uint16_t * g_chom_sensor_table[CHOM_NUM_OF_SENSORS] = +{ // Node total power (DC) + &g_amec_sys.sys.pwr250us.sample, + // Socket power + &g_amec_sys.proc[0].pwr250us.sample, + &G_dcom_slv_outbox_rx[1].pwr250usp0, + &G_dcom_slv_outbox_rx[2].pwr250usp0, + &G_dcom_slv_outbox_rx[3].pwr250usp0, + &G_dcom_slv_outbox_rx[4].pwr250usp0, + &G_dcom_slv_outbox_rx[5].pwr250usp0, + &G_dcom_slv_outbox_rx[6].pwr250usp0, + &G_dcom_slv_outbox_rx[7].pwr250usp0, + // Memory power + &G_dcom_slv_outbox_rx[0].pwr250usmemp0, + &G_dcom_slv_outbox_rx[1].pwr250usmemp0, + &G_dcom_slv_outbox_rx[2].pwr250usmemp0, + &G_dcom_slv_outbox_rx[3].pwr250usmemp0, + &G_dcom_slv_outbox_rx[4].pwr250usmemp0, + &G_dcom_slv_outbox_rx[5].pwr250usmemp0, + &G_dcom_slv_outbox_rx[6].pwr250usmemp0, + &G_dcom_slv_outbox_rx[7].pwr250usmemp0, + // Fan power + &g_amec_sys.fan.pwr250usfan.sample, + // Processor frequency + &G_dcom_slv_outbox_rx[0].freqa2msp0, + &G_dcom_slv_outbox_rx[1].freqa2msp0, + &G_dcom_slv_outbox_rx[2].freqa2msp0, + &G_dcom_slv_outbox_rx[3].freqa2msp0, + &G_dcom_slv_outbox_rx[4].freqa2msp0, + &G_dcom_slv_outbox_rx[5].freqa2msp0, + &G_dcom_slv_outbox_rx[6].freqa2msp0, + &G_dcom_slv_outbox_rx[7].freqa2msp0, + // Processor utilization sensor + &G_dcom_slv_outbox_rx[0].util2msp0, + &G_dcom_slv_outbox_rx[1].util2msp0, + &G_dcom_slv_outbox_rx[2].util2msp0, + &G_dcom_slv_outbox_rx[3].util2msp0, + &G_dcom_slv_outbox_rx[4].util2msp0, + &G_dcom_slv_outbox_rx[5].util2msp0, + &G_dcom_slv_outbox_rx[6].util2msp0, + &G_dcom_slv_outbox_rx[7].util2msp0, + // Max Core temperature for all processors in the node + NULL, + // Max Centaur temperature for all Centaurs in the node + NULL, + // Max Dimm temperature for all Dimms in the node + NULL, + // Instructions per second sensor + NULL, + // Memory bandwidth for process memory controller + // P0M0 ~ P0M7 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // P1M0 ~ P1M7 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // P2M0 ~ P2M7 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // P3M0 ~ P3M7 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // P4M0 ~ P4M7 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // P5M0 ~ P5M7 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // P6M0 ~ P6M7 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // P7M0 ~ P7M7 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + +// Function Specification +// +// Name: chom_data_init +// +// Description: Init chom data +// +// End Function Specification +void chom_data_init() +{ + // chom data reset + chom_data_reset(); + // update eyecatcher + memcpy(&g_chom->nodeData.eyecatcher, "CHOM", 0x04); + // update chom version + g_chom->nodeData.version = CHOM_VERSION; + // update num of sensors + g_chom->nodeData.numSensors = CHOM_NUM_OF_SENSORS; +} + + +// Function Specification +// +// Name: chom_data_reset +// +// Description: Reset chom data +// +// End Function Specification +void chom_data_reset() +{ + // reset chom data log + memset(g_chom, 0x00, sizeof(*g_chom)); + // reset chom modes in log + memset(g_chom_pwr_modes, 0x00, sizeof(g_chom_pwr_modes)); + // reset chom timer + g_chom_gen_periodic_log_timer = 0; + // reset flag + g_chom_force = FALSE; + +} + + +// Function Specification +// +// Name: chom_update_sensors +// +// Description: Update chom sensor data +// +// End Function Specification +void chom_update_sensors() +{ + uint16_t l_max_core_temp = 0; + uint16_t l_max_cent_temp = 0; + uint16_t l_max_dimm_temp = 0; + uint16_t l_mips = 0; + uint16_t l_mem_rw = 0; + uint16_t l_sample = 0; + uint16_t i = 0, j = 0, k = 0; + + // Is the current mode different than previous poll + if (g_chom->nodeData.curPwrMode != CURRENT_MODE()) + { + // update current power mode + g_chom->nodeData.curPwrMode = CURRENT_MODE(); + // copy the current mode data to previous mode + memcpy(&g_chom->sensorData[1], &g_chom->sensorData[0], sizeof(ChomSensorData_t)); + // reset all fields in the current chom sensors + memset(&g_chom->sensorData[0], 0x00, sizeof(ChomSensorData_t)); + // update power saving mode of sensor data + g_chom->sensorData[0].pwrMode.mode = g_chom->nodeData.curPwrMode; + + // initial min value of chom sensors + for (i=0 ; isensorData[0].sensor[i].sampleMin = 0xffff; + } + + // update the number of power modes during the polling period + switch (g_chom->nodeData.curPwrMode) + { + case OCC_MODE_NOMINAL: + g_chom_pwr_modes[OCC_INTERNAL_MODE_NOM] = 1; + break; + + case OCC_MODE_PWRSAVE: + g_chom_pwr_modes[OCC_INTERNAL_MODE_SPS] = 1; + break; + + case OCC_MODE_DYN_POWER_SAVE: + g_chom_pwr_modes[OCC_INTERNAL_MODE_DPS] = 1; + break; + + case OCC_MODE_DYN_POWER_SAVE_FP: + g_chom_pwr_modes[OCC_INTERNAL_MODE_DPS_MP] = 1; + break; + + case OCC_MODE_FFO: + g_chom_pwr_modes[OCC_INTERNAL_MODE_FFO] = 1; + break; + + default: + TRAC_INFO("chom_update_sensors: Cannot record chom data for mode 0x%02X", + g_chom->sensorData[0].pwrMode.mode); + break; + } + } + + // update number of samples + g_chom->sensorData[0].pwrMode.numOfSamples++; + + // update chom sensors which has multiple mini-sensor source + for (i = 0 ; i l_max_core_temp) + { + l_max_core_temp = G_dcom_slv_outbox_rx[i].temp2msp0peak; + } + + if (G_dcom_slv_outbox_rx[i].temp2mscent > l_max_cent_temp) + { + l_max_cent_temp = G_dcom_slv_outbox_rx[i].temp2mscent; + } + + if (G_dcom_slv_outbox_rx[i].temp2msdimm > l_max_dimm_temp) + { + l_max_dimm_temp = G_dcom_slv_outbox_rx[i].temp2msdimm; + } + } + g_chom->sensorData[0].sensor[CHOMTEMPPROC].sample = l_max_core_temp; + g_chom->sensorData[0].sensor[CHOMTEMPCENT].sample = l_max_cent_temp; + g_chom->sensorData[0].sensor[CHOMTEMPDIMM].sample = l_max_dimm_temp; + + // update MIPS + k = 0; + for (i=0 ; isensorData[0].sensor[CHOMIPS].sample = (l_mips/k); + } + + // update memory bandwidth + k = CHOMBWP0M0; + for (i=0 ; isensorData[0].sensor[k].sample = l_mem_rw; + k++; + } + } + + // loop through all sensors and update data from mini-sensors + for (i = 0 ; i= CHOMPWRS0) && (i <= CHOMPWRS7)) && + (CFAM_CHIP_TYPE_MURANO == cfam_chip_type()) && + (((i-CHOMPWRS0) % 2) == 1) ) + { + //Do nothing + } + else + { + // directly mapping to mini-sensor + g_chom->sensorData[0].sensor[i].sample = *g_chom_sensor_table[i]; + } + } + + l_sample = g_chom->sensorData[0].sensor[i].sample; + + if (g_chom->sensorData[0].sensor[i].sampleMin > l_sample) + { + g_chom->sensorData[0].sensor[i].sampleMin = l_sample; + } + if (g_chom->sensorData[0].sensor[i].sampleMax < l_sample) + { + g_chom->sensorData[0].sensor[i].sampleMax = l_sample; + } + g_chom->sensorData[0].sensor[i].accumulator += l_sample; + g_chom->sensorData[0].sensor[i].average = (g_chom->sensorData[0].sensor[i].accumulator/ + g_chom->sensorData[0].pwrMode.numOfSamples); + } +} + + +// Function Specification +// +// Name: chom_collect_cpi_data +// +// Description: collect CPI data +// +// End Function Specification +void chom_collect_cpi_data(void) +{ + // TODO +} + + +// Function Specification +// +// Name: chom_gen_periodic_log +// +// Description: Create call home data logs +// +// End Function Specification +void chom_gen_periodic_log() +{ + uint8_t i = 0; + errlHndl_t l_errlHndl = NULL; + + TRAC_INFO("Enter chom_gen_periodic_log"); + + // update total time + g_chom->nodeData.totalTime = g_chom_gen_periodic_log_timer; + + // update the number of different power modes + for (i=0 ; inodeData.modeInLog++; + } + } + + // collect CPI data + chom_collect_cpi_data(); + + /* @ + * @errortype + * @moduleid THRD_MID_GEN_CALLHOME_LOG + * @reasoncode GEN_CALLHOME_LOG + * @userdata1 0 + * @userdata2 0 + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Generating periodic call-home log, which contains critical power/thermal/performance data since the last log was generated (or the last OCC reset) + */ + l_errlHndl = createErrl( + THRD_MID_GEN_CALLHOME_LOG, // modId + GEN_CALLHOME_LOG, // reasoncode + OCC_NO_EXTENDED_RC, // Extended reason code + ERRL_SEV_CALLHOME_DATA, // Severity; will be changed to informational in errl.c + NULL, // Trace Buf + 0, // Trace Size + 0, // userdata1 + 0 // userdata2 + ); + + // add chom data + addUsrDtlsToErrl(l_errlHndl, + (uint8_t*)g_chom, + sizeof(*g_chom), + ERRL_STRUCT_VERSION_1, + ERRL_USR_DTL_CALLHOME_DATA); + + // commit error log + if (l_errlHndl != NULL) + { + commitErrl(&l_errlHndl); + } +} + + +// Function Specification +// +// Name: chom_force_gen_log() +// +// Description: immediate chom log +// +// End Function Specification +void chom_force_gen_log() +{ + g_chom_force = TRUE; +} + + +// Function Specification +// +// Name: chom_main +// +// Description: Call home data routine +// +// End Function Specification +void chom_main() +{ + MAIN_DBG("CHOM routine processing..."); + + // check if this is the first time we run + if (memcmp(&g_chom->nodeData.eyecatcher, "CHOM", 0x04) != 0) + { + chom_data_init(); + } + + // only update chom sensors on an active OCC + if (IS_OCC_STATE_ACTIVE()) + { + chom_update_sensors(); + } + + // increase chom timer + g_chom_gen_periodic_log_timer++; + + // check if the timer expired + if ((g_chom_gen_periodic_log_timer >= CHOM_GEN_LOG_PERIODIC_TIME) || + (TRUE == g_chom_force)) + { + chom_gen_periodic_log(); + chom_data_reset(); + } +} diff --git a/src/occ_405/thread/chom.h b/src/occ_405/thread/chom.h new file mode 100755 index 0000000..b899e9e --- /dev/null +++ b/src/occ_405/thread/chom.h @@ -0,0 +1,231 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ/thread/chom.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 */ + +#ifndef _CHOM_H +#define _CHOM_H + +#include +#include + +#define CHOM_GEN_LOG_PERIODIC_TIME 86400 // seconds in a day +#define CHOM_VERSION 0x00 +// Max size of chom data log +#define CHOM_LOG_DATA_MAX 3072 + +// List of call home sensors +enum +{ + // Node total power (DC) + CHOMPWR = 0, + // Socket power + CHOMPWRS0, + CHOMPWRS1, + CHOMPWRS2, + CHOMPWRS3, + CHOMPWRS4, + CHOMPWRS5, + CHOMPWRS6, + CHOMPWRS7, + // Memory power + CHOMPWRM0, + CHOMPWRM1, + CHOMPWRM2, + CHOMPWRM3, + CHOMPWRM4, + CHOMPWRM5, + CHOMPWRM6, + CHOMPWRM7, + // Fan power + CHOMPWRFAN, + // Processor frequency + CHOMFREQP0, + CHOMFREQP1, + CHOMFREQP2, + CHOMFREQP3, + CHOMFREQP4, + CHOMFREQP5, + CHOMFREQP6, + CHOMFREQP7, + // Processor utilization sensor + CHOMUTILP0, + CHOMUTILP1, + CHOMUTILP2, + CHOMUTILP3, + CHOMUTILP4, + CHOMUTILP5, + CHOMUTILP6, + CHOMUTILP7, + // Max core temperature for all processors in the node + CHOMTEMPPROC, + // Max Centaur temperature for all Centaurs in the node + CHOMTEMPCENT, + // Max Dimm temperature for all Dimms in the node + CHOMTEMPDIMM, + // Instructions per second sensor + CHOMIPS, + // Memory bandwidth for process memory controller + CHOMBWP0M0, + CHOMBWP0M1, + CHOMBWP0M2, + CHOMBWP0M3, + CHOMBWP0M4, + CHOMBWP0M5, + CHOMBWP0M6, + CHOMBWP0M7, + CHOMBWP1M0, + CHOMBWP1M1, + CHOMBWP1M2, + CHOMBWP1M3, + CHOMBWP1M4, + CHOMBWP1M5, + CHOMBWP1M6, + CHOMBWP1M7, + CHOMBWP2M0, + CHOMBWP2M1, + CHOMBWP2M2, + CHOMBWP2M3, + CHOMBWP2M4, + CHOMBWP2M5, + CHOMBWP2M6, + CHOMBWP2M7, + CHOMBWP3M0, + CHOMBWP3M1, + CHOMBWP3M2, + CHOMBWP3M3, + CHOMBWP3M4, + CHOMBWP3M5, + CHOMBWP3M6, + CHOMBWP3M7, + CHOMBWP4M0, + CHOMBWP4M1, + CHOMBWP4M2, + CHOMBWP4M3, + CHOMBWP4M4, + CHOMBWP4M5, + CHOMBWP4M6, + CHOMBWP4M7, + CHOMBWP5M0, + CHOMBWP5M1, + CHOMBWP5M2, + CHOMBWP5M3, + CHOMBWP5M4, + CHOMBWP5M5, + CHOMBWP5M6, + CHOMBWP5M7, + CHOMBWP6M0, + CHOMBWP6M1, + CHOMBWP6M2, + CHOMBWP6M3, + CHOMBWP6M4, + CHOMBWP6M5, + CHOMBWP6M6, + CHOMBWP6M7, + CHOMBWP7M0, + CHOMBWP7M1, + CHOMBWP7M2, + CHOMBWP7M3, + CHOMBWP7M4, + CHOMBWP7M5, + CHOMBWP7M6, + CHOMBWP7M7, + + // The number of chom sensors reported + CHOM_NUM_OF_SENSORS +}; + +// Call home sensor Structure +struct ChomSensor +{ + uint16_t sample; // last sample value during the polling period + uint16_t sampleMin; // min sample value recorded during polling period + uint16_t sampleMax; // max sample value recorded during polling period + uint16_t average; // average sample value during polling period + uint32_t accumulator; // accumulator register to computer the average +} __attribute__ ((__packed__)); + +typedef struct ChomSensor ChomSensor_t; + +// CPI data structure +struct ChomCpiData +{ + uint8_t proc; + uint32_t cpi; +}__attribute__ ((__packed__)); + +typedef struct ChomCpiData ChomCpiData_t; + +// Power mode structure +struct ChomPwrMode +{ + uint8_t mode; // OCC power mode + uint32_t numOfSamples; // Number of times samples were polled while in this mode +}__attribute__ ((__packed__)); + +typedef struct ChomPwrMode ChomPwrMode_t; + +// Call home data structure +struct ChomNodeData +{ + uint32_t eyecatcher; // "CHOM" will mark the beginning of the data + uint8_t version; // version of call home data being reported + uint8_t curPwrMode; // the current power mode at the time of the polling event + uint32_t totalTime; // duration of the polling period + uint8_t modeInLog; // the number of different power mode in the polling period + ChomCpiData_t cpiData[MAX_OCCS]; // Chip Packing Interface data, 5 bytes per processor + uint16_t numSensors; // the number of sensors for which call home data was collected +} __attribute__ ((__packed__)); + +typedef struct ChomNodeData ChomNodeData_t; + +// Call home sensor data +struct ChomSensorData +{ + ChomPwrMode_t pwrMode; + ChomSensor_t sensor[CHOM_NUM_OF_SENSORS]; +}__attribute__ ((__packed__)); + +typedef struct ChomSensorData ChomSensorData_t; + +// Call home log data +struct ChomLogData +{ + ChomNodeData_t nodeData; // general node data + ChomSensorData_t sensorData[2]; // sensors data (current and previous power mode) +}__attribute__ ((__packed__)); + +typedef struct ChomLogData ChomLogData_t; + +extern uint32_t g_chom_gen_periodic_log_timer; +extern ChomLogData_t * g_chom; +extern uint8_t g_chom_force; + +void chom_data_init(); +void chom_update_sensors(); +void chom_gen_periodic_log(); +void chom_data_reset(); +void chom_force_gen_log(); +void chom_main(); + +#endif //_CHOM_H diff --git a/src/occ_405/thread/test/Makefile b/src/occ_405/thread/test/Makefile new file mode 100755 index 0000000..62863ba --- /dev/null +++ b/src/occ_405/thread/test/Makefile @@ -0,0 +1,64 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/occ_405/thread/test/Makefile $ +# +# 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 + +threadtest_CFILES = \ + ../../common.c \ + ../../errl/errl.c \ + ../threadSch.c \ + threadtest.c + +all_cfiles = ${threadtest_CFILES} + +APP = threadtest +APP_INCLUDES += -I../../../ssx +APP_INCLUDES += -I../../../lib +APP_INCLUDES += -I../../incl +APP_INCLUDES += -I../../trac +APP_INCLUDES += -I../../errl +APP_INCLUDES += -I../../thread +APP_INCLUDES += -I../../aplt/incl +APP_INCLUDES += -I. + + + +#D = -DVERIFICATION=1 \ + -DSSX_STACK_CHECK=0 \ + -DINITIALIZE_PMC=0 \ + -DINITIALIZE_SIMICS_IO=0 \ + -DINITIALIZE_RTX_IO=1 \ + -DINITIALIZE_PBA=1 \ + -DSIMICS_MAGIC_PANIC=1 \ + -DSSX_KERNEL_TRACE_ENABLE=1 + + +SOURCES = ${all_cfiles} +MODE = validation + +PGP_ASYNC_SUPPORT = 1 + +include ./app.mk + +pgas: + $(CC) $(CFLAGS) -c -Wa,-al -Wa,--listing-cont-lines='10' diff --git a/src/occ_405/thread/test/app.mk b/src/occ_405/thread/test/app.mk new file mode 100755 index 0000000..b5001d5 --- /dev/null +++ b/src/occ_405/thread/test/app.mk @@ -0,0 +1,79 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/occ_405/thread/test/app.mk $ +# +# 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 + +OCC = ../../ +SSX = ../../../ssx +LIB = ../../../lib +PGP = $(SSX)/pgp + +ifeq "$(MODE)" "firmware" +SSX_TIMER_SUPPORT = 0 +SSX_THREAD_SUPPORT = 0 +endif + +export SSX_TIMER_SUPPORT +export SSX_THREAD_SUPPORT +export PPC405_MMU_SUPPORT +export PGP_ASYNC_SUPPORT + +INCLUDES = -I $(OCC) -I$(LIB) + +include $(PGP)/ssx.mk + +C-OBJECTS = $(SOURCES:.c=.o) +OBJECTS = $(C-OBJECTS:.S=.o) + +LDFLAGS = -L $(SSX)/ssx -L $(SSX)/ppc32 -L $(SSX)/ppc405 -L $(SSX)/pgp \ + -L $(OCC) -L $(LIB) -lssx -lppc32 + +DEFS += $(D) + +all: $(OBJECTS) libssx.a + $(MAKE) -C $(PGP) DEFS="$(DEFS)" -e + $(CPP) -P $(DEFS) < $(OCC)/linkocc.cmd > linkscript + $(LD) $(OBJECTS) \ + -Tlinkscript $(LDFLAGS) -Map $(APP).map -Bstatic -o $(APP).out + $(OBJCOPY) -O binary $(APP).out $(APP).bin + $(OBJDUMP) -d $(APP).out > $(APP).dis + +libssx.a: + $(MAKE) -C $(LIB) DEFS="$(DEFS)" -e + + +.PHONY : clean +clean: + rm -f *.o *.d *.d.* *.out *.bin *.srec *.dis *.map linkscript + rm -f ./*/*.o ./*/*.d ./*/*.d.* + +.PHONY : clean_all +clean_all: + $(MAKE) clean + $(MAKE) -C $(PGP) clean + +.PHONY : doc +doc: + doxygen doc/Doxyfile + +-include $(OBJECTS:.o=.d) diff --git a/src/occ_405/thread/test/threadtest.c b/src/occ_405/thread/test/threadtest.c new file mode 100755 index 0000000..0aced6c --- /dev/null +++ b/src/occ_405/thread/test/threadtest.c @@ -0,0 +1,317 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/thread/test/threadtest.c $ */ +/* */ +/* 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 */ + +#include "ssx.h" +#include "ssx_io.h" +#include "simics_stdio.h" +#include +#include +#include +#include +#include + +extern void __ssx_boot; + +IMAGE_HEADER (G_mainAppImageHdr,__ssx_boot,MAIN_APP_ID,OCC_APLT_TEST); + +// Period in which to run timer_routine +#define TIMER_INTERVAL (SsxInterval) SSX_MICROSECONDS(5000) + +SsxSemaphore prcd_sem; + +int g_j = 0; +int g_k = 0; +/*----------------------------------------------------------------------------*/ +/* noncrtical/critical stack */ +/*----------------------------------------------------------------------------*/ +uint8_t noncritical_stack[NONCRITICAL_STACK_SIZE]; +uint8_t critical_stack[CRITICAL_STACK_SIZE]; +SimicsStdio simics_stdout; +SimicsStdio simics_stderr; + +SsxTimer G_test_timer; + +extern void timer_routine(void *private); +extern void rtloop_ocb_init(void); + + +// Function Specification +// +// Name: pgp_validation_ssx_main_hook +// +// Description: TODO Add description +// +// End Function Specification +void pgp_validation_ssx_main_hook(void) +{ + +} + +// Function Specification +// +// Name: Cmd_Hndl_thread_routine +// +// Description: TODO Add description +// +// End Function Specification +//TODO placeholder +void Cmd_Hndl_thread_routine(void *arg) +{ + do + { + int x=0; + for(x=0; x < 1000; x++) + { + + } + }while(1); + +} + +// Function Specification +// +// Name: App_thread_routine +// +// Description: TODO Add description +// +// End Function Specification +void App_thread_routine(void *arg) +{ + int z=0; + do + { + int x=0; + for(x=0; x < 10000; x++) + { + z++; + } + }while(1); + +} + +// Function Specification +// +// Name: Thermal_Monitor_thread_routine +// +// Description: TODO Add description +// +// End Function Specification +void Thermal_Monitor_thread_routine(void *arg) +{ + int z=0; + do + { + int x=0; + for(x=0; x < 10000; x++) + { + z++; + } + }while(1); + +} + +// Function Specification +// +// Name: Hlth_Monitor_thread_routine +// +// Description: TODO Add description +// +// End Function Specification +void Hlth_Monitor_thread_routine(void *arg) +{ + int z=0; + do + { + int x=0; + for(x=0; x < 10000; x++) + { + z++; + } + }while(1); + +} + +// Function Specification +// +// Name: FFDC_thread_routine +// +// Description: TODO Add description +// +// End Function Specification +void FFDC_thread_routine(void *arg) +{ + int z=0; + do + { + int x=0; + for(x=0; x < 10000; x++) + { + z++; + } + }while(1); + +} + +// Function Specification +// +// Name: main_thread_routine +// +// Description: This thread currently just looks as the lowest priority thread, +// handling the lowest priority tasks. +// +// End Function Specification +void main_thread_routine(void *private) +{ + // Start the critical 250uS timer + ssx_timer_schedule(&timer, 1, TIMER_INTERVAL); + + while(1) + { + // Only trace the first XX times that this function loops + if(g_k < 3) + { + g_k++; + + // TRACE: Main Thread + } + + // Sleep for 1000 before we run the loop again + ssx_sleep_absolute(1000); + } +} + +// Function Specification +// +// Name: timer_routine +// +// Description: TODO Add description +// +// End Function Specification +void timer_routine (void *arg) +{ + +} + +// Function Specification +// +// Name: dump_thread_info +// +// Description: TODO Add description +// +// End Function Specification +void dump_thread_info(void *arg) +{ + + printf("dumping thread info--------------------------\n"); + int l_rc = 0; + SsxThreadState l_state = 0; + SsxThreadPriority l_pri = 0; + int l_runnable=0; + int x=0; + for(x=0; x < THREADS_TO_SCHEDULE; x++) + { + l_rc = ssx_thread_info_get(G_scheduledThreads[x], + &l_state, + &l_pri, + &l_runnable); + + printf("Thread %p: State %x priority %x runnable %x rc %x Global index %x\n",G_scheduledThreads[x], + l_state, + l_pri, + l_runnable, + l_rc, + G_threadSchedulerIndex); + + } + +} + +// Function Specification +// +// Name: main +// +// Description: Initializes the trace buffer, along with creating threads and timers +// for execution. Note that once main runs with ssx_start_threads, we +// never return as the SSX kernel takes over. +// +// End Function Specification +int main(int argc, char **argv) +{ + // Locals + errlHndl_t l_errl = INVALID_ERR_HNDL; + + // Initialize Trace Buffers immediately, so they can be used + // from this point on. + + // Initialize stdout so we can do printf from within simics env + simics_stdout_create(&simics_stdout); + simics_stderr_create(&simics_stderr); + stdout = (FILE *)(&simics_stdout); + stderr = (FILE *)(&simics_stderr); + + // Initialize SSX Stacks (note that this also reinitializes the time base to 0) + ssx_initialize((SsxAddress)noncritical_stack, NONCRITICAL_STACK_SIZE, + (SsxAddress)critical_stack, CRITICAL_STACK_SIZE, 0); + + // Create Global Semaphores + ssx_semaphore_create(&prcd_sem, 0, 13); + + ssx_timer_create(&timer, timer_routine, 0); + + // Create thread with already mapped priority + // Create Threads + ssx_thread_create(&main_thread, + main_thread_routine, + (void *)0, + (SsxAddress)main_thread_stack, + THREAD_STACK_SIZE, + 0); + + // Make Threads runnable + ssx_thread_resume(&main_thread); + + //Initialize the thread scheduler + l_errl = initThreadScheduler(); + + if(l_errl) + { + // TODO Trace the error + + // Commit log + // NOTE: log should be deleted by reader mechanism + commitErrl( &l_errl ); + } + + // Kick off timer + ssx_timer_create(&G_test_timer, dump_thread_info, 0); + ssx_timer_schedule(&G_test_timer, 1, 500000000); + + + // Enter SSX Kernel + ssx_start_threads(); + + return 0; +} + diff --git a/src/occ_405/thread/thread.h b/src/occ_405/thread/thread.h new file mode 100755 index 0000000..3106a7c --- /dev/null +++ b/src/occ_405/thread/thread.h @@ -0,0 +1,88 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/thread/thread.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 */ + +#ifndef _THREAD_H +#define _THREAD_H + +#include +#include "ssx.h" + +// Thread priorities for Thread creation. +typedef enum +{ + THREAD_PRIORITY_0, // Reserved for high priority + THREAD_PRIORITY_1, // Reserved for high priority + THREAD_PRIORITY_2, + THREAD_PRIORITY_3, + THREAD_PRIORITY_4, + THREAD_PRIORITY_5, + THREAD_PRIORITY_6, + THREAD_PRIORITY_7, + THREAD_PRIORITY_8, +}THREAD_PRIORITY; + +// NOTE: Stack sizes are defined by entity +// - Non-Critical Stack used by non-critical interrupt handlers, including timer callbacks +// - Critical Stack used for critical interrupts +// - Stacks for each thread +#define NONCRITICAL_STACK_SIZE 8192 // 8kB +#define CRITICAL_STACK_SIZE 4096 // 4kB +#define THREAD_STACK_SIZE 4096 // 4kB + +extern uint8_t main_thread_stack[THREAD_STACK_SIZE]; +extern uint8_t Cmd_hndl_thread_stack[THREAD_STACK_SIZE]; +extern uint8_t App_thread_stack[THREAD_STACK_SIZE]; +extern uint8_t testAppletThreadStack[THREAD_STACK_SIZE]; + +/*----------------------------------------------------------*/ +/* SsxThread Declaration */ +/*----------------------------------------------------------*/ + +// Our idle thread. See main_thread_routine +extern SsxThread Main_thread; + +// Command handler thread +extern SsxThread Cmd_Hndl_thread; + +// Application manager thread +extern SsxThread App_thread; + +// Test applet thread +extern SsxThread TestAppletThread; + +// Application manager thread +extern SsxThread Dcom_thread; + +void Main_thread_routine(void *private); + +void Cmd_Hndl_thread_routine(void *arg); + +void App_thread_routine(void *arg); + +void Dcom_thread_routine(void *arg); + +void testAppletThreadRoutine(void *arg); + +#endif //_THREAD_H diff --git a/src/occ_405/thread/threadSch.c b/src/occ_405/thread/threadSch.c new file mode 100755 index 0000000..cfb996e --- /dev/null +++ b/src/occ_405/thread/threadSch.c @@ -0,0 +1,322 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/thread/threadSch.c $ */ +/* */ +/* 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 */ + +#include +#include +#include "ssx.h" +#include "thread_service_codes.h" +#include "occ_service_codes.h" +#include +#include +#include +#include "cmdh_snapshot.h" + +// Numbers of threads to schedule +#define THREADS_TO_SCHEDULE (sizeof(G_scheduledThreads)/sizeof(SsxThread*)) + +#define THREAD_TIME_SLICE (SsxInterval) SSX_MILLISECONDS(10) // 10ms + +// Thread Timer to reprioritize the threads +SsxTimer G_threadSchTimer; + +// Index of highest priority thread in G_scheduledThreads +uint16_t G_threadSchedulerIndex = 0; + +// Array that holds the threads that need scheduling +SsxThread* G_scheduledThreads[] = +{ + &Main_thread, + &Cmd_Hndl_thread, + &App_thread, + &TestAppletThread, + &Dcom_thread, +}; + +// Error log counter for the callback so that only 1 error log is created +uint8_t G_threadSwapErrlCounter = 0; + +// Global for the parameter to the applet thread routine +OCC_APLT_TYPE G_apltPdtType = APLT_TYPE_PRODUCT; +OCC_APLT_TYPE G_apltTestType = APLT_TYPE_TEST; + +//Thread Stacks +uint8_t main_thread_stack[THREAD_STACK_SIZE]; +uint8_t Cmd_hndl_thread_stack[THREAD_STACK_SIZE]; +uint8_t App_thread_stack[THREAD_STACK_SIZE]; +uint8_t testAppletThreadStack[THREAD_STACK_SIZE]; +uint8_t dcomThreadStack[THREAD_STACK_SIZE]; + +// Our idle thread. See main_thread_routine +SsxThread Main_thread; + +// Command handler thread +SsxThread Cmd_Hndl_thread; + +// Application manager thread +SsxThread App_thread; + +// Test applet thread +SsxThread TestAppletThread; + +// Dcom thread +SsxThread Dcom_thread; + +// Function Specification +// +// Name: createAndResumeThreadHelper +// +// Description: create and resume thread helper +// +// End Function Specification +int createAndResumeThreadHelper(SsxThread *io_thread, + SsxThreadRoutine i_thread_routine, + void *io_arg, + SsxAddress i_stack, + size_t i_stack_size, + THREAD_PRIORITY i_priority) +{ + + // Locals + int l_rc = SSX_OK; + + // Thread creation + l_rc = ssx_thread_create(io_thread, + i_thread_routine, + io_arg, + i_stack, + i_stack_size, + (SsxThreadPriority)i_priority); + + //check for errors creating a thread + if(l_rc != SSX_OK) + { + TRAC_ERR("Failure creating thread. rc: 0x%x", -l_rc); + } + else + { + //resume thread once created + l_rc = ssx_thread_resume(io_thread); + } + + + return l_rc; +} + +// Function Specification +// +// Name: initThreadScheduler +// +// Description: Init the threads in the scheduler and start the +// timer. +// +// End Function Specification +void initThreadScheduler(void) +{ + // Locals + int l_appThreadRc = SSX_OK; + int l_cmdThreadRc = SSX_OK; + int l_timerRc = SSX_OK; + int l_testAppletThreadRc = SSX_OK; + int l_dcomThreadRc = SSX_OK; + int l_snapshotTimerRc = SSX_OK; + + // Creating threads that need to be scheduled + // Thread priority range should match scheduled + // threads in G_scheduledThreads ie highest priority thread should be + // index 0 of G_scheduledThreads + + l_cmdThreadRc = createAndResumeThreadHelper(&Cmd_Hndl_thread, + Cmd_Hndl_thread_routine, + (void *)0, + (SsxAddress)Cmd_hndl_thread_stack, + THREAD_STACK_SIZE, + THREAD_PRIORITY_3); + + l_appThreadRc = createAndResumeThreadHelper(&App_thread, + App_thread_routine, + (void *)&G_apltPdtType, + (SsxAddress)App_thread_stack, + THREAD_STACK_SIZE, + THREAD_PRIORITY_4); + + l_testAppletThreadRc = createAndResumeThreadHelper(&TestAppletThread, + App_thread_routine, + (void *)&G_apltTestType, + (SsxAddress)testAppletThreadStack, + THREAD_STACK_SIZE, + THREAD_PRIORITY_5); + + l_dcomThreadRc = createAndResumeThreadHelper(&Dcom_thread, + Dcom_thread_routine, + (void *)0, + (SsxAddress)dcomThreadStack, + THREAD_STACK_SIZE, + THREAD_PRIORITY_6); + + // Create the thread scheduler timer + l_timerRc = ssx_timer_create(&G_threadSchTimer, threadSwapcallback, 0); + + // Check for errors creating the timer + if(l_timerRc == SSX_OK) + { + TRAC_INFO("timer created and scheduled"); + //schedule the timer so that it runs every THREAD_TIME_SLICE + l_timerRc = ssx_timer_schedule(&G_threadSchTimer, 1, THREAD_TIME_SLICE); + } + else + { + TRAC_INFO("Error creating timer: RC: %d", l_timerRc); + } + + // Create snapshot timer + l_snapshotTimerRc = ssx_timer_create(&G_snapshotTimer, cmdh_snapshot_callback, 0); + + // Check for errors creating the timer + if(l_snapshotTimerRc == SSX_OK) + { + // Schedule the timer so that it runs every 30 seconds. + l_snapshotTimerRc = ssx_timer_schedule(&G_snapshotTimer, 0, SSX_SECONDS(30)); + if (l_snapshotTimerRc != SSX_OK) + { + TRAC_ERR("cmdh_snapshot_sync: reseting the snapshot timer failed."); + } + } + else + { + TRAC_INFO("Error creating timer: RC: %d", l_snapshotTimerRc); + } + + // If there are any errors creating the threads or starting the + // timer create an error log to pass back. + if( l_appThreadRc + || l_testAppletThreadRc + || l_cmdThreadRc + || l_dcomThreadRc + || l_timerRc + || l_snapshotTimerRc ) + { + TRAC_ERR("Error creating thread: l_appThreadRc: %d, " + "l_testAppletThreadRc: %d, l_cmdThreadRc: %d, " + "l_dcomThreadRc: %d", l_appThreadRc,l_testAppletThreadRc, + l_timerRc,l_cmdThreadRc,l_dcomThreadRc); + TRAC_ERR("Error starting timers: timerRc: %d, snapshotTimerRc: %d.", + l_timerRc, l_snapshotTimerRc); + // Create error log and log it + // TODO use correct trace + tracDesc_t l_trace = NULL; + + /* @ + * @errortype + * @moduleid THRD_MID_INIT_THREAD_SCHDLR + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 Schedule timer return code + * @userdata2 Snapshot timer return code + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc SSX thread related failure + */ + errlHndl_t l_rc = createErrl(THRD_MID_INIT_THREAD_SCHDLR, // ModId + SSX_GENERIC_FAILURE, // Reasoncode + OCC_NO_EXTENDED_RC, // Extended reasoncode + ERRL_SEV_UNRECOVERABLE, // Severity + l_trace, // Trace Buf + DEFAULT_TRACE_SIZE, // Trace Size + l_timerRc, // Userdata1 + l_snapshotTimerRc); // Userdata2 + + REQUEST_RESET(l_rc); + } +} + + +// Function Specification +// +// Name: threadSwapcallback +// +// Description: a periodic timer callback to swap prorities of scheduled threads +// +// End Function Specification +void threadSwapcallback(void * arg) +{ + // Locals + int l_rc = SSX_OK; + + // Current location of index in scheduled thread array + int l_threadAIndex = G_threadSchedulerIndex; + + // If global index == last item swap priorities with 1st + int l_threadBIndex = (G_threadSchedulerIndex == (THREADS_TO_SCHEDULE-1)) ? 0 : ++G_threadSchedulerIndex; + + // Swap priorities with global index +1 + l_rc = ssx_thread_priority_swap(G_scheduledThreads[l_threadAIndex],G_scheduledThreads[l_threadBIndex]); + + if(l_rc != SSX_OK) + { + // TODO trace error + + // Create and commit error log + if(G_threadSwapErrlCounter == 0) + { + // TODO use correct trace + tracDesc_t l_trace = NULL; + + /* + * @errortype + * @moduleid THRD_MID_THREAD_SWAP_CALLBACK + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 Return code of thread priority swap + * @userdata2 Current location of index in scheduled thread array + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc SSX thread related failure + */ + errlHndl_t l_err = createErrl( + THRD_MID_THREAD_SWAP_CALLBACK, // ModId + SSX_GENERIC_FAILURE, // Reasoncode + OCC_NO_EXTENDED_RC, // Extended reasoncode + ERRL_SEV_PREDICTIVE, // Severity + l_trace, // Trace Buf + DEFAULT_TRACE_SIZE, // Trace Size + l_rc, // Userdata1 + l_threadAIndex // Userdata2 + ); + + // Commit log + // NOTE: Log should be deleted by reader mechanism + commitErrl( &l_err ); + + // Increment errl counter + G_threadSwapErrlCounter++; + + }// End thread swap counter if + } + else + { + // Reset counter since it started working again + G_threadSwapErrlCounter = 0; + + // Set the global to the new location of the highest priority thread + G_threadSchedulerIndex = l_threadBIndex; + } +} + diff --git a/src/occ_405/thread/threadSch.h b/src/occ_405/thread/threadSch.h new file mode 100755 index 0000000..124d460 --- /dev/null +++ b/src/occ_405/thread/threadSch.h @@ -0,0 +1,49 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/thread/threadSch.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 */ + +#ifndef _THREADSCH_H +#define _THREADSCH_H + +#include +#include +#include "ssx.h" +#include + +// Function to reprioritize the threads in the array +void threadSwapcallback(void * arg); + +// Function to initilize the threads and the thread schedule timer +void initThreadScheduler(void) INIT_SECTION; + +// Function to create and resume thread. Externalizing as it is used to +// create main thread +int createAndResumeThreadHelper(SsxThread *io_thread, + SsxThreadRoutine i_thread_routine, + void *io_arg, + SsxAddress i_stack, + size_t i_stack_size, + THREAD_PRIORITY i_priority); + +#endif //_THREADSCH_H diff --git a/src/occ_405/thread/thread_service_codes.h b/src/occ_405/thread/thread_service_codes.h new file mode 100755 index 0000000..6d13baa --- /dev/null +++ b/src/occ_405/thread/thread_service_codes.h @@ -0,0 +1,48 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/thread/thread_service_codes.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 */ + +// NOTE: The thread component will not actually generate errors +// using the thread component. This is due to the fact that will +// use trace so therefore we can induce non-ending recursion if trace +// were to use ERRL. + +// A trace failure is not a system critical failure which is why we +// can get away with it not reporting errors. + +#ifndef _THREAD_SERVICE_CODES_H_ +#define _THREAD_SERVICE_CODES_H_ + +#include + +enum thrdModuleId +{ + THRD_MID_INIT_THREAD_SCHDLR = THRD_COMP_ID | 0x00, + THRD_MID_THREAD_SWAP_CALLBACK = THRD_COMP_ID | 0x01, + THRD_MID_GEN_CALLHOME_LOG = THRD_COMP_ID | 0x02, + THRD_THERMAL_VRM_FAN_CONTROL = THRD_COMP_ID | 0x03, + THRD_THERMAL_MAIN = THRD_COMP_ID | 0x04, +}; + +#endif /* #ifndef _THREAD_SERVICE_CODES_H_ */ diff --git a/src/occ_405/thread/thrm_thread.c b/src/occ_405/thread/thrm_thread.c new file mode 100755 index 0000000..13d9423 --- /dev/null +++ b/src/occ_405/thread/thrm_thread.c @@ -0,0 +1,459 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/thread/thrm_thread.c $ */ +/* */ +/* 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 */ + +#include +#include +#include +#include +#include +#include +#include + +// Global for notifying the thermal thread if it needs to update its copy +// of the thermal threshold data packet (format 0x13) +BOOLEAN G_thrm_parms_need_update = FALSE; + +// Fan control loop time in seconds sent by TMGT (format 0x13) +uint8_t G_thrm_loop_time = 0; + +// Cooling request status (0=no request; 1=send request) +uint8_t G_thrm_cooling_request = 0; + +// Local copy of thermal thresholds sent by TMGT (format 0x13) +thrm_fru_control_t G_thrm_fru_control[DATA_FRU_MAX]; + +// Global array to store dynamic information for each FRU +thrm_fru_data_t G_thrm_fru_data[DATA_FRU_MAX]; + +// Function Specification +// +// Name: THRM_thread_update_thresholds +// +// Description: Notify thermal thread to update its local copy of the +// thermal threshold data packet. +// +// End Function Specification +void THRM_thread_update_thresholds() +{ + G_thrm_parms_need_update = TRUE; +} + +// Function Specification +// +// Name: THRM_thread_get_cooling_request +// +// Description: Get the status of the cooling request from the thermal +// thread. +// +// End Function Specification +uint8_t THRM_thread_get_cooling_request() +{ + return G_thrm_cooling_request; +} + +// Function Specification +// +// Name: thrm_thread_load_thresholds +// +// Description: Read thermal thresholds sent by TMGT (data format 0x13) +// and store them for thermal thread consumption. +// +// End Function Specification +errlHndl_t thrm_thread_load_thresholds() +{ + errlHndl_t l_err = NULL; + cmdh_thrm_thresholds_t *l_data = NULL; + uint8_t i = 0; + + do + { + // Get thermal threshold data sent by TMGT + l_err = DATA_get_thrm_thresholds(&l_data); + if(l_err) + { + TRAC_ERR("thrm_thread_load_thresholds: Thermal control thresholds not available!"); + + // This is a critical failure since we can't run the fan control + // without the thermal thresholds. Make the fan control loop time + // zero so that we don't execute any fan control + G_thrm_loop_time = 0; + break; + } + + // Load fan control loop time + G_thrm_loop_time = l_data->fan_control_loop_time; + + TRAC_INFO("thrm_thread_load_thresholds: Fan Control loop time[%u]", + G_thrm_loop_time); + + // Load FRU data + for (i=0; idata[i].warning; + G_thrm_fru_control[i].warning_reset = l_data->data[i].warning_reset; + G_thrm_fru_control[i].t_inc_zone[0] = l_data->data[i].t_inc_zone1; + G_thrm_fru_control[i].t_inc_zone[1] = l_data->data[i].t_inc_zone2; + G_thrm_fru_control[i].t_inc_zone[2] = l_data->data[i].t_inc_zone3; + G_thrm_fru_control[i].t_inc_zone[3] = l_data->data[i].t_inc_zone4; + G_thrm_fru_control[i].t_inc_zone[4] = l_data->data[i].t_inc_zone5; + G_thrm_fru_control[i].t_inc_zone[5] = l_data->data[i].t_inc_zone6; + G_thrm_fru_control[i].t_inc_zone[6] = l_data->data[i].t_inc_zone7; + G_thrm_fru_control[i].t_inc_zone[7] = l_data->data[i].t_inc_zone8; + + // Load data that depends on the system mode + // Acoustic mode takes priority + if (0) // TODO: Need to implement acoustic mode + { + G_thrm_fru_control[i].t_control = l_data->data[i].acoustic_t_control; + G_thrm_fru_control[i].error = l_data->data[i].acoustic_error; + } + // ...then nominal mode + else if (CURRENT_MODE() == OCC_MODE_NOMINAL) + { + G_thrm_fru_control[i].t_control = l_data->data[i].t_control; + G_thrm_fru_control[i].error = l_data->data[i].error; + } + // ...then any other power management mode + else + { + G_thrm_fru_control[i].t_control = l_data->data[i].pm_t_control; + G_thrm_fru_control[i].error = l_data->data[i].pm_error; + } + + TRAC_INFO("thrm_thread_load_thresholds: Using t_control[%u] error[%u] for FRU[0x%02X]", + G_thrm_fru_control[i].t_control, + G_thrm_fru_control[i].error, + i); + } + }while(0); + + return(l_err); + +} + + +// Function Specification +// +// Name: thrm_thread_fan_control +// +// Description: Execute the fan control algorithm for the specified FRU. +// Returns TRUE or FALSE depending whether we need to increase fan speeds +// or not. +// +// End Function Specification +BOOLEAN thrm_thread_fan_control(const uint8_t i_fru_type, + const uint16_t i_fru_temperature) +{ + eConfigDataFruType k = i_fru_type; + BOOLEAN l_IncreaseFans = FALSE; + uint8_t i = 0; + uint16_t l_delta_temp = 0; + + //If there's a read error, assume temperature is t_control + 1 + if(G_thrm_fru_data[k].read_failure) + { + G_thrm_fru_data[k].Tcurrent = G_thrm_fru_control[k].t_control + 1; + } + else + { + // Collect the current FRU temperature + G_thrm_fru_data[k].Tcurrent = i_fru_temperature; + } + + // Is the current FRU temperature bigger than the FRU T_control? + if (G_thrm_fru_data[k].Tcurrent > G_thrm_fru_control[k].t_control) + { + // Is the current temperature below the previous temperature? + if (G_thrm_fru_data[k].Tcurrent < G_thrm_fru_data[k].Tprevious) + { + // Temperature is decreasing so we don't need to request any + // additional cooling + G_thrm_fru_data[k].temp_increasing = FALSE; + } + else if (G_thrm_fru_data[k].Tcurrent > G_thrm_fru_data[k].Tprevious) + { + // Temperature is increasing and we need to request more cooling + G_thrm_fru_data[k].temp_increasing = TRUE; + l_IncreaseFans = TRUE; + } + else + { + // Temperature is the same as previous iteration. Check the trend + // to see whether is increasing or decreasing + if (G_thrm_fru_data[k].temp_increasing == TRUE) + { + // Need to request additional cooling + l_IncreaseFans = TRUE; + } + else + { + // No need to request additional cooling + } + } + } + + // Prepare the cooling requests for all Zones + l_delta_temp = G_thrm_fru_data[k].Tcurrent - G_thrm_fru_control[k].t_control; + + if (l_IncreaseFans == TRUE) + { + for (i = 0; i < THRM_MAX_NUM_ZONES; i++) + { + G_thrm_fru_data[k].FanIncZone[i] = l_delta_temp * + G_thrm_fru_control[k].t_inc_zone[i]; + } + } + else + { + for (i = 0; i < THRM_MAX_NUM_ZONES; i++) + { + G_thrm_fru_data[k].FanIncZone[i] = 0; + } + } + + // Store the current temperature for next iteration + G_thrm_fru_data[k].Tprevious = G_thrm_fru_data[k].Tcurrent; + + return(l_IncreaseFans); +} + + +// Function Specification +// +// Name: thrm_thread_vrm_fan_control +// +// Description: Execute the fan control algorithm for VRM based on the +// VR_FAN signal. Returns TRUE or FALSE depending whether we need to increase +// fan speeds or not. +// +// End Function Specification +BOOLEAN thrm_thread_vrm_fan_control(const uint16_t i_vrfan) +{ + BOOLEAN l_IncreaseFans = FALSE; + static BOOLEAN L_error_logged = FALSE; + uint8_t i = 0; + errlHndl_t l_err = NULL; + + if ((i_vrfan == 1) || (G_thrm_fru_data[DATA_FRU_VRM].read_failure == 1)) + { + // If VR_FAN has been asserted or we cannot read it, request one T_INC + // for each zone to be controlled + l_IncreaseFans = TRUE; + + for (i = 0; i < THRM_MAX_NUM_ZONES; i++) + { + G_thrm_fru_data[DATA_FRU_VRM].FanIncZone[i] = + G_thrm_fru_control[DATA_FRU_VRM].t_inc_zone[i]; + } + + // Log an informational error the first time VR_FAN was asserted (this + // is for manufacturing mode IPLs) + if (i_vrfan == 1) + { + if (!L_error_logged) + { + L_error_logged = TRUE; + + TRAC_ERR("thrm_thread_vrm_fan_control: VR_FAN for this regulator has been asserted!"); + + /* @ + * @errortype + * @moduleid THRD_THERMAL_VRM_FAN_CONTROL + * @reasoncode VRM_VRFAN_ASSERTED + * @userdata1 state of VR_FAN signal + * @userdata2 0 + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc VR_FAN signal from regulator has been asserted. + * + */ + l_err = createErrl(THRD_THERMAL_VRM_FAN_CONTROL, //modId + VRM_VRFAN_ASSERTED, //reasoncode + OCC_NO_EXTENDED_RC, //Extended reason code + ERRL_SEV_INFORMATIONAL, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + i_vrfan, //userdata1 + 0); //userdata2 + + // Set the manufacturing error flag in the log + setErrlActions(l_err, ERRL_ACTIONS_MANUFACTURING_ERROR); + + // Commit the error + commitErrl(&l_err); + } + } + } + else + { + // If VR_FAN is de-asserted, don't send any cooling requests + l_IncreaseFans = FALSE; + + for (i = 0; i < THRM_MAX_NUM_ZONES; i++) + { + G_thrm_fru_data[DATA_FRU_VRM].FanIncZone[i] = 0; + } + } + + return(l_IncreaseFans); +} + +// Function Specification +// +// Name: thrm_thread_main +// +// Description: Main thermal thread routine +// +// End Function Specification +void thrm_thread_main() +{ + errlHndl_t l_err = NULL; + BOOLEAN l_IncreaseFans = FALSE; + sensor_t *l_sensor = NULL; + static uint8_t L_counter = 0; + static BOOLEAN L_full_speed_log = FALSE; + + // Execute fan control loop if OCC is in observation state or active state + // AND if we have received the thermal threshold data packet + if (((CURRENT_STATE() == OCC_STATE_OBSERVATION) || + (CURRENT_STATE() == OCC_STATE_ACTIVE)) && + (DATA_get_present_cnfgdata() & DATA_MASK_THRM_THRESHOLDS)) + { + // Check if we need to update our local copy of the thermal threshold + // data packet + if (G_thrm_parms_need_update) + { + // Clear this flag now that we are going to update our local copy + G_thrm_parms_need_update = FALSE; + + // Update our local copy of the thermal thresholds + l_err = thrm_thread_load_thresholds(); + + if (l_err) + { + // Commit error log for failing to load thermal thresholds + commitErrl(&l_err); + } + else + { + // Clear our counter that determines when to run the fan + // control loop + L_counter = 0; + } + } + + // Increment our counter and make sure it doesn't wrap + L_counter++; + // The fan control loop time is only 1-byte long. A loop time of 0 + // indicates that we shouldn't run the fan control loop. + if (L_counter == 0) + { + L_counter = 0xFF; + } + + // Is it time to execute the fan control loop? + if (L_counter == G_thrm_loop_time) + { + // Reset our counter + L_counter = 0; + + // Determine if additional cooling is required for VRMs + l_sensor = getSensorByGsid(VRFAN250USPROC); + l_IncreaseFans |= thrm_thread_vrm_fan_control(l_sensor->sample); + + // Determine if additional cooling is required for processors + // For processors, use the hottest of the core averages + l_sensor = getSensorByGsid(TEMP2MSP0PEAK); + l_IncreaseFans |= thrm_thread_fan_control(DATA_FRU_PROC, + l_sensor->sample); + + // Determine if additional cooling is required for centaurs + l_sensor = getSensorByGsid(TEMP2MSCENT); + l_IncreaseFans |= thrm_thread_fan_control(DATA_FRU_CENTAUR, + l_sensor->sample); + + // Determine if additional cooling is required for dimms + l_sensor = getSensorByGsid(TEMP2MSDIMM); + l_IncreaseFans |= thrm_thread_fan_control(DATA_FRU_DIMM, + l_sensor->sample); + + // Do we need to request a fan increase? + if (l_IncreaseFans == TRUE) + { + // Set 'Cooling Request' for the poll response + G_thrm_cooling_request = 1; + + // Send 'Service' attention to FSP to force TMGT to send poll + // command + cmdh_fsp_attention(OCC_ALERT_FSP_SERVICE_REQD); + + // Check if fans are currently already at max (known from APSS) + // log informational B1812A08 and have the "Manufacturing error" + // bit in the actions field set so that TMGT will flag this in manufacturing. + // ** No longer reading gpio from APSS in GA1 due to instability in APSS composite mode + uint8_t l_full_speed = 1; // low active + // TODO: Should we continue to not read gpio from APSS? + if( (L_full_speed_log == FALSE) && + FALSE) //apss_gpio_get(l_full_speed_pin,&l_full_speed) ) + { + if(l_full_speed == 0) //low active + { + L_full_speed_log = TRUE; // log this error ONLY ONCE per IPL + TRAC_ERR("thrm_thread_main: Request a fan increase and fan is already in full speed"); + + /* @ + * @errortype + * @moduleid THRD_THERMAL_MAIN + * @reasoncode FAN_FULL_SPEED + * @userdata1 0 + * @userdata2 0 + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Request a fan increase and fan is already in full speed + * + */ + l_err = createErrl(THRD_THERMAL_MAIN, //modId + FAN_FULL_SPEED, //reasoncode + OCC_NO_EXTENDED_RC, //Extended reason code + ERRL_SEV_INFORMATIONAL, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + 0, //userdata1 + 0); //userdata2 + + // Set the manufacturing error flag in the log + setErrlActions(l_err, ERRL_ACTIONS_MANUFACTURING_ERROR); + commitErrl(&l_err); + } + } + // + } + else + { + // Reset the 'Cooling Request' since we don't need a fan increase + G_thrm_cooling_request = 0; + } + } + } +} diff --git a/src/occ_405/thread/thrm_thread.h b/src/occ_405/thread/thrm_thread.h new file mode 100755 index 0000000..21a8b8e --- /dev/null +++ b/src/occ_405/thread/thrm_thread.h @@ -0,0 +1,62 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/thread/thrm_thread.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 */ + +#ifndef THRM_THREAD_H +#define THRM_THREAD_H + +#define THRM_MAX_NUM_ZONES 8 + +typedef struct thrm_fru_control +{ + uint8_t t_control; + uint8_t error; + uint8_t warning; + uint8_t warning_reset; + uint16_t t_inc_zone[THRM_MAX_NUM_ZONES]; +}thrm_fru_control_t; + +typedef struct thrm_fru_data +{ + // Flag to indicate that we have timed out trying to read this thermal sensor + uint8_t read_failure; + // Current temperature of this FRU + uint16_t Tcurrent; + // Previous temperature of this FRU + uint16_t Tprevious; + // Coooling requests to be sent back to TMGT + uint16_t FanIncZone[THRM_MAX_NUM_ZONES]; + // Flag to indicate if the temperature for this FRU is increasing or not + BOOLEAN temp_increasing; +}thrm_fru_data_t; + +errlHndl_t thrm_thread_load_thresholds(); +void THRM_thread_update_thresholds(); +uint8_t THRM_thread_get_cooling_request(); +BOOLEAN thrm_thread_fan_control(const uint8_t i_frutype, + const uint16_t i_fru_temperature); +BOOLEAN thrm_thread_vrm_fan_control(const uint16_t i_vrfan); +void thrm_thread_main(); + +#endif -- cgit v1.2.1