diff options
| author | William Bryan <wilbryan@us.ibm.com> | 2016-12-12 14:12:31 -0600 |
|---|---|---|
| committer | William A. Bryan <wilbryan@us.ibm.com> | 2016-12-15 13:57:45 -0500 |
| commit | 48173d1181eb89c7efed5d6ffd30c8e89666aee5 (patch) | |
| tree | 8df43001cd86a38a5df61ef335ff8749b1d3042e /src/tools | |
| parent | e29c6746a230904209290fa6d2a940898c581639 (diff) | |
| download | talos-occ-48173d1181eb89c7efed5d6ffd30c8e89666aee5.tar.gz talos-occ-48173d1181eb89c7efed5d6ffd30c8e89666aee5.zip | |
FFDC parsing tool
Change-Id: Iada745ba30af2b4d6160770b2e2fc82c15b5d523
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33746
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com>
Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
Diffstat (limited to 'src/tools')
| -rw-r--r-- | src/tools/ffdcparser/Makefile | 26 | ||||
| -rw-r--r-- | src/tools/ffdcparser/ffdcparser.c | 382 |
2 files changed, 408 insertions, 0 deletions
diff --git a/src/tools/ffdcparser/Makefile b/src/tools/ffdcparser/Makefile new file mode 100644 index 0000000..3521af1 --- /dev/null +++ b/src/tools/ffdcparser/Makefile @@ -0,0 +1,26 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/ffdcparser/Makefile $ +# +# OpenPOWER OnChipController Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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: ffdcparser.c + gcc ffdcparser.c -o ../../../obj/ppetools/ffdcparser diff --git a/src/tools/ffdcparser/ffdcparser.c b/src/tools/ffdcparser/ffdcparser.c new file mode 100644 index 0000000..4c45936 --- /dev/null +++ b/src/tools/ffdcparser/ffdcparser.c @@ -0,0 +1,382 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/ffdcparser/ffdcparser.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF 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 <stdint.h> + +// NOTE: This tool is to be used when FFDC is dumped by the OCC, and currently +// only accepts input files in binary format. + +typedef struct thread_dump +{ + uint8_t len; + uint8_t pri; + uint8_t state; + uint8_t flags; + uint32_t timer; + uint32_t sem; + uint32_t srr0; + uint32_t srr1; + uint32_t srr2; + uint32_t srr3; + uint32_t lr; + uint32_t stack_trace[8]; +} thread_dump_t; + +// FFDC struct +typedef struct __attribute__((packed,aligned(4))) ffdc +{ + uint8_t seq; // Sequence Number (0x00 for FFDC) + uint8_t cmd; // Command (0x00 for FFDC) + uint8_t excp; // Exception Code + uint16_t len; // FFDC data length + uint8_t reserved; // (0x00 for FFDC) + uint16_t ckpt; // Checkpoint (usually 0x0F00 for FFDC) + uint32_t ssx_panic; // SSX Panic Code + uint32_t panic_addr; // Address of panic instruction + uint32_t lr; // Link Register + uint32_t msr; // Machine Status Register + uint32_t cr; // Condition Register + uint32_t ctr; // Count Register + uint32_t gpr[32]; // GPR0 - GPR31 + uint32_t evpr; // Exception Vector Prefix Register + uint32_t xer; // Fixedpoint Exception Register + uint32_t esr; // Exception Syndrome Register + uint32_t dear; // Bad Address + uint32_t srr0; // Return Address for Non-Crit Interrupts + uint32_t srr1; // MSR at time of non-crit interrupt + uint32_t srr2; // Return Address for Crit Interrupts + uint32_t srr3; // MSR at time of crit interrupt + uint32_t mcsr; // Machine Check Syndrome Register + uint32_t pid; // Process ID Register + uint32_t zpr; // Zone Protection Register + uint32_t usprg0; // User SPR General Purpose Register + uint32_t sprg[8]; // SPRG0 - SPRG7 + uint32_t tcr; // Timer Control Register + uint32_t tsr; // Timer Status Register + uint32_t dbcr0; // Debug Control Register0 + uint32_t dbcr1; // Debug Control Register1 + uint32_t dbsr; // Debug Status Register + uint32_t ocb_oisr0; + uint32_t ocb_oisr1; + uint32_t ocb_ouder0; + uint32_t ocb_ouder1; + uint32_t ocb_oimr0; + uint32_t ocb_oimr1; + uint32_t ocb_oitr0; + uint32_t ocb_oitr1; + uint32_t ocb_oiepr0; + uint32_t ocb_oiepr1; + uint32_t ocb_ocir0; + uint32_t ocb_ocir1; + uint32_t ocb_onisr0; + uint32_t ocb_onisr1; + uint32_t ocb_ocisr0; + uint32_t ocb_ocisr1; + uint32_t ocb_her0; + uint32_t ocb_her1; + uint32_t ssx_timebase; + char buildname[16]; + uint64_t occlfir; + uint64_t pbafir; + uint32_t cores_deconf; + thread_dump_t main; + thread_dump_t cmdh; + thread_dump_t dcom; + uint32_t stack_trace[8]; + uint32_t eye_catcher; +} ffdc_t; + +uint64_t get_uint64(FILE* i_fhndl) +{ + int i = 0; + uint64_t ret = 0; + uint8_t byte = 0; + + for(i = 7; i >= 0; i--) + { + byte = fgetc(i_fhndl); + if(EOF != byte) + { + ret |= (byte << (i*8)); + } + } + + return ret; +} + +uint32_t get_uint32(FILE* i_fhndl) +{ + int i = 0; + uint32_t ret = 0; + uint8_t byte = 0; + + for(i = 3; i >= 0; i--) + { + byte = fgetc(i_fhndl); + if(EOF != byte) + { + ret |= (byte << (i*8)); + } + } + + return ret; +} + +uint16_t get_uint16(FILE* i_fhndl) +{ + int i = 0; + uint16_t ret = 0; + uint8_t byte = 0; + + for(i = 1; i >= 0; i--) + { + byte = fgetc(i_fhndl); + if(EOF != byte) + { + ret |= (byte << (i*8)); + } + } + + return ret; +} + +int file_length_valid(FILE* i_fhndl, uint16_t i_exp_size) +{ + uint32_t len = 0; + + while(EOF != fgetc(i_fhndl)) + { + len++; + } + + return (len < i_exp_size) ? 0 : 1; +} + +void get_thread_data(FILE* i_fhndl, thread_dump_t * i_thrd) +{ + uint32_t i = 0; + i_thrd->len = fgetc(i_fhndl); + i_thrd->pri = fgetc(i_fhndl); + i_thrd->state = fgetc(i_fhndl); + i_thrd->flags = fgetc(i_fhndl); + i_thrd->timer = get_uint32(i_fhndl); + i_thrd->sem = get_uint32(i_fhndl); + i_thrd->srr0 = get_uint32(i_fhndl); + i_thrd->srr1 = get_uint32(i_fhndl); + i_thrd->srr2 = get_uint32(i_fhndl); + i_thrd->srr3 = get_uint32(i_fhndl); + i_thrd->lr = get_uint32(i_fhndl); + for(i = 0; i < 8; i++) + i_thrd->stack_trace[i] = get_uint32(i_fhndl); +} + +void print_thread_data(thread_dump_t * i_thrd, char* i_name) +{ + uint32_t i = 0; + + printf("%s Thread Dump\n", i_name); + printf("\tPriority: 0x%02X\n", i_thrd->pri); + printf("\tState: 0x%02X\n", i_thrd->state); + printf("\tFlags: 0x%02X\n", i_thrd->flags); + printf("\tTimer: 0x%08X\n", i_thrd->timer); + printf("\tSemaphore: 0x%08X\n", i_thrd->sem); + printf("\tSRR0: 0x%08X\n", i_thrd->srr0); + printf("\tSRR1: 0x%08X\n", i_thrd->srr1); + printf("\tSRR2: 0x%08X\n", i_thrd->srr2); + printf("\tSRR3: 0x%08X\n", i_thrd->srr3); + printf("\tStack Trace\n"); + for(i = 0; i < 8; i++) + printf("\t\t%d: 0x%08X\n", i+1, i_thrd->stack_trace[i]); +} + +void dump_ffdc(ffdc_t * data) +{ + uint32_t i = 0; + + printf("Exception Code: 0x%02X\n", data->excp); + printf("Checkpoint: 0x%04X\n", data->ckpt); + printf("SSX Panic Code: 0x%08X\n", data->ssx_panic); + printf("Panic Address: 0x%08X\n", data->panic_addr); + printf("LR: 0x%08X\n", data->lr); + printf("MSR: 0x%08X\n", data->msr); + printf("CR: 0x%08X\n", data->cr); + printf("CTR: 0x%08X\n", data->ctr); + for(i = 0; i < 32; i++) + printf("GPR%d: 0x%08X\n", i, data->gpr[i]); + printf("EVPR: 0x%08X\n", data->evpr); + printf("XER: 0x%08X\n", data->xer); + printf("ESR: 0x%08X\n", data->esr); + printf("DEAR: 0x%08X\n", data->dear); + printf("SRR0: 0x%08X\n", data->srr0); + printf("SRR1: 0x%08X\n", data->srr1); + printf("SRR2: 0x%08X\n", data->srr2); + printf("SRR3: 0x%08X\n", data->srr3); + printf("MCSR: 0x%08X\n", data->mcsr); + printf("PID:: 0x%08X\n", data->pid); + printf("ZPR: 0x%08X\n", data->zpr); + printf("USPRG0: 0x%08X\n", data->usprg0); + for(i = 0; i < 8; i++) + printf("SPRG%d: 0x%08X\n", i, data->sprg[i]); + printf("TCR: 0x%08X\n", data->tcr); + printf("TSR: 0x%08X\n", data->tsr); + printf("DBCR0: 0x%08X\n", data->dbcr0); + printf("DBCR1: 0x%08X\n", data->dbcr1); + printf("DBSR: 0x%08X\n", data->dbsr); + printf("OCB_OISR0: 0x%08X\n", data->ocb_oisr0); + printf("OCB_OISR1: 0x%08X\n", data->ocb_oisr1); + printf("OCB_OUDER0: 0x%08X\n", data->ocb_ouder0); + printf("OCB_OUDER1: 0x%08X\n", data->ocb_ouder1); + printf("OCB_OIMR0: 0x%08X\n", data->ocb_oimr0); + printf("OCB_OIMR1: 0x%08X\n", data->ocb_oimr1); + printf("OCB_OITR0: 0x%08X\n", data->ocb_oitr0); + printf("OCB_OITR1: 0x%08X\n", data->ocb_oitr1); + printf("OCB_OIEPR0: 0x%08X\n", data->ocb_oiepr0); + printf("OCB_OIEPR1: 0x%08X\n", data->ocb_oiepr1); + printf("OCB_OCIR0: 0x%08X\n", data->ocb_ocir0); + printf("OCB_OCIR1: 0x%08X\n", data->ocb_ocir1); + printf("OCB_ONISR0: 0x%08X\n", data->ocb_onisr0); + printf("OCB_ONISR1: 0x%08X\n", data->ocb_onisr1); + printf("OCB_OCISR0: 0x%08X\n", data->ocb_ocisr0); + printf("OCB_OCISR1: 0x%08X\n", data->ocb_ocisr1); + printf("OCB_HER0: 0x%08X\n", data->ocb_her0); + printf("OCB_HER1: 0x%08X\n", data->ocb_her1); + printf("SSX Timebase: 0x%08X\n", data->ssx_timebase); + printf("OCC Buildname: %s\n", data->buildname); + printf("OCC LFIR: 0x%016X\n", data->occlfir); + printf("PBA FIR: 0x%016X\n", data->pbafir); + printf("Cores Deconfigured: 0x%08X\n", data->cores_deconf); + print_thread_data(&data->main, "MAIN"); + print_thread_data(&data->cmdh, "CMDH"); + print_thread_data(&data->dcom, "DCOM"); + printf("Stack Trace:\n"); + for(i = 0; i < 8; i++) + printf("\t%d: 0x%08X\n", i+1, data->stack_trace[i]); +} + +int main(int argc, char** argv) +{ + FILE* ffdc_file = NULL; + ffdc_t data = {0}; + uint32_t i = 0; + + // Verify a file was passed as an argument + if(argc < 2) + { + fprintf(stderr, "ERROR: Requires a file with the binary FFDC data\n"); + return -1; + } + else + { + ffdc_file = fopen(argv[1], "rb"); + if(ffdc_file == NULL) + { + fprintf(stderr, "ERROR: %s cannot be opened or does not exist\n", argv[1]); + return -1; + } + } + + // Binary file is open, parse it + data.seq = fgetc(ffdc_file); + data.cmd = fgetc(ffdc_file); + data.excp = fgetc(ffdc_file); + data.len = get_uint16(ffdc_file); + + if( (!file_length_valid(ffdc_file, data.len)) ) + { + fprintf(stderr, "ERROR: FFDC file not valid size\n"); + return -1; + } + + if(fseek(ffdc_file, 5, SEEK_SET)) + { + fprintf(stderr, "ERROR: Something happened when changing offsets in ffdc file\n"); + return -1; + } + + data.reserved = fgetc(ffdc_file); + data.ckpt = get_uint16(ffdc_file); + data.ssx_panic = get_uint32(ffdc_file); + data.panic_addr = get_uint32(ffdc_file); + data.lr = get_uint32(ffdc_file); + data.msr = get_uint32(ffdc_file); + data.cr = get_uint32(ffdc_file); + data.ctr = get_uint32(ffdc_file); + for(i = 0; i < 32; i++) + data.gpr[i] = get_uint32(ffdc_file); + data.evpr = get_uint32(ffdc_file); + data.xer = get_uint32(ffdc_file); + data.esr = get_uint32(ffdc_file); + data.dear = get_uint32(ffdc_file); + data.srr0 = get_uint32(ffdc_file); + data.srr1 = get_uint32(ffdc_file); + data.srr2 = get_uint32(ffdc_file); + data.srr3 = get_uint32(ffdc_file); + data.mcsr = get_uint32(ffdc_file); + data.pid = get_uint32(ffdc_file); + data.zpr = get_uint32(ffdc_file); + data.usprg0 = get_uint32(ffdc_file); + for(i = 0; i < 8; i++) + data.sprg[i] = get_uint32(ffdc_file); + data.tcr = get_uint32(ffdc_file); + data.tsr = get_uint32(ffdc_file); + data.dbcr0 = get_uint32(ffdc_file); + data.dbcr1 = get_uint32(ffdc_file); + data.dbsr = get_uint32(ffdc_file); + data.ocb_oisr0 = get_uint32(ffdc_file); + data.ocb_oisr1 = get_uint32(ffdc_file); + data.ocb_ouder0 = get_uint32(ffdc_file); + data.ocb_ouder1 = get_uint32(ffdc_file); + data.ocb_oimr0 = get_uint32(ffdc_file); + data.ocb_oimr1 = get_uint32(ffdc_file); + data.ocb_oitr0 = get_uint32(ffdc_file); + data.ocb_oitr1 = get_uint32(ffdc_file); + data.ocb_oiepr0 = get_uint32(ffdc_file); + data.ocb_oiepr1 = get_uint32(ffdc_file); + data.ocb_ocir0 = get_uint32(ffdc_file); + data.ocb_ocir1 = get_uint32(ffdc_file); + data.ocb_onisr0 = get_uint32(ffdc_file); + data.ocb_onisr1 = get_uint32(ffdc_file); + data.ocb_ocisr0 = get_uint32(ffdc_file); + data.ocb_ocisr1 = get_uint32(ffdc_file); + data.ocb_her0 = get_uint32(ffdc_file); + data.ocb_her1 = get_uint32(ffdc_file); + data.ssx_timebase = get_uint32(ffdc_file); + fgets(data.buildname, 16, ffdc_file); + fgetc(ffdc_file); + data.occlfir = get_uint64(ffdc_file); + data.pbafir = get_uint64(ffdc_file); + data.cores_deconf = get_uint32(ffdc_file); + get_thread_data(ffdc_file, &data.main); + get_thread_data(ffdc_file, &data.cmdh); + get_thread_data(ffdc_file, &data.dcom); + for(i=0; i<8; i++) + data.stack_trace[i] = get_uint32(ffdc_file); + data.eye_catcher = get_uint32(ffdc_file); + dump_ffdc(&data); + if(data.eye_catcher != 0xFFDCFFDC) + printf("WARNING: Eye catcher(0x%08X) was not 0xFFDCFFDC\n", data.eye_catcher); + + return 0; +} |

