meta-facebook/meta-fbttn/recipes-fbttn/me-util/files/me-util.c (360 lines of code) (raw):

/* * me-util * * Copyright 2015-present Facebook. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <syslog.h> #include <stdint.h> #include <pthread.h> #include <string.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <facebook/bic.h> #include <openbmc/ipmi.h> #define MAX_PROC_ID 31 #define MAX_MC_IDX 19 #define MAX_RETRY 0 #define ME_COLD_RESET_DELAY 5 #define LOGFILE "/tmp/me-util.log" #define CRASHDUMP_FILE "/mnt/data/crashdump_slot1" #define IA32_MC_CTL_base 0x0400 #define IA32_MC_CTL2_base 0x0280 #define IA32_MC_STATUS_base 0x0401 #define IA32_MC_ADDR_base 0x0402 #define IA32_MC_MISC_base 0x0403 #define IA32_MCG_CAP 0x0179 #define IA32_MCG_STATUS 0x017A #define IA32_MCG_CONTAIN 0x0178 static void print_usage_help(void) { printf("Usage: me-util <server> <netfn/LUN> <cmd> <data bytes to send>\n"); printf("Usage: me-util <server> 48 coreid\n"); printf("Usage: me-util <server> 48 msr\n"); printf(" *48 coreid/msr data will be saved at /mnt/data/crashdump_slot1\n"); } int crash_dump_msr(void) { FILE *fp = NULL; int processorid = 0, retry = 0, response = 0, comp = 1, mc_index = 0, msr_offset = 0; uint16_t param, param0, param1, cmdout; uint8_t slot_id = 1; uint8_t tbuf[256] = {0x00}; uint8_t rbuf[256] = {0x00}; uint8_t tlen = 0; uint8_t rlen = 0; uint8_t check; //for check 4th response data int i = 0; fp = fopen(CRASHDUMP_FILE, "a+"); if (!fp) { printf("File open Fail\n"); return -1; } fprintf(fp, "\n"); fprintf(fp, "%s\n", "MSR DUMP:"); fprintf(fp, "%s\n", "========="); fprintf(fp, "\n"); while( mc_index <= MAX_MC_IDX ) { fprintf(fp, "********************************************************\n"); fprintf(fp, "* MC index %02d *\n", mc_index); fprintf(fp, "********************************************************\n"); ////////////////////////////////////////////////////////////////////////////////////////////////////////// fprintf(fp, " <<< IA32_MC%d_CTL, ProcessorID from 0 to %d >>> \n", mc_index, MAX_PROC_ID); processorid = 0; retry = 0; while( processorid <= MAX_PROC_ID ) { param = IA32_MC_CTL_base + msr_offset; param0 = ( param & 0xFF ); param1 = ( param >> 8 ); tbuf[0] = 0xB8; tbuf[1] = 0x40; tbuf[2] = 0x57; tbuf[3] = 0x01; tbuf[4] = 0x00; tbuf[5] = 0x30; tbuf[6] = 0x05; tbuf[7] = 0x09; tbuf[8] = 0xb1; tbuf[9] = 0x00; tbuf[10] = processorid; tbuf[11] = param0; tbuf[12] = param1; tlen = 13; comp = bic_me_xmit(slot_id, tbuf, tlen, rbuf, &rlen); check = rbuf[3]; if( (( check == 0x80 ) || ( check = 0x81 ) || ( check == 0x81 ) || ( comp != 0 )) && ( retry < MAX_RETRY ) ) { retry++; sleep(1); } else { for ( i = 0 ; i < rlen ; i ++ ) fprintf(fp, "%02X ", rbuf[i]); fprintf(fp, "\n"); processorid++; retry = 0; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////// fprintf(fp, " <<< IA32_MC%d_CTL2, ProcessorID from 0 to %d >>> \n", mc_index, MAX_PROC_ID); processorid = 0; retry = 0; while( processorid <= MAX_PROC_ID ) { param = IA32_MC_CTL2_base + mc_index; param0 = ( param & 0xFF ); param1 = ( param >> 8 ); tbuf[10] = processorid; tbuf[11] = param0; tbuf[12] = param1; comp = bic_me_xmit(slot_id, tbuf, tlen, rbuf, &rlen); check = rbuf[3]; if( (( check == 0x80 ) || ( check = 0x81 ) || ( check == 0x81 ) || ( comp != 0 )) && ( retry < MAX_RETRY ) ) { retry++; sleep(1); } else { for ( i = 0 ; i < rlen ; i ++ ) fprintf(fp, "%02X ", rbuf[i]); fprintf(fp, "\n"); processorid++; retry = 0; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////// fprintf(fp, " <<< IA32_MC%d_STATUS, ProcessorID from 0 to %d >>> \n", mc_index, MAX_PROC_ID); processorid = 0; retry = 0; while( processorid <= MAX_PROC_ID ) { param = IA32_MC_STATUS_base + msr_offset; param0 = ( param & 0xFF ); param1 = ( param >> 8 ); tbuf[10] = processorid; tbuf[11] = param0; tbuf[12] = param1; comp = bic_me_xmit(slot_id, tbuf, tlen, rbuf, &rlen); check = rbuf[3]; if( (( check == 0x80 ) || ( check = 0x81 ) || ( check == 0x81 ) || ( comp != 0 )) && ( retry < MAX_RETRY ) ) { retry++; sleep(1); } else { for ( i = 0 ; i < rlen ; i ++ ) fprintf(fp, "%02X ", rbuf[i]); fprintf(fp, "\n"); processorid++; retry = 0; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////// fprintf(fp, " <<< IA32_MC%d_ADDR, ProcessorID from 0 to %d >>> \n", mc_index, MAX_PROC_ID); processorid = 0; retry = 0; while( processorid <= MAX_PROC_ID ) { param = IA32_MC_ADDR_base + msr_offset; param0 = ( param & 0xFF ); param1 = ( param >> 8 ); tbuf[10] = processorid; tbuf[11] = param0; tbuf[12] = param1; comp = bic_me_xmit(slot_id, tbuf, tlen, rbuf, &rlen); check = rbuf[3]; if( (( check == 0x80 ) || ( check = 0x81 ) || ( check == 0x81 ) || ( comp != 0 )) && ( retry < MAX_RETRY ) ) { retry++; sleep(1); } else { for ( i = 0 ; i < rlen ; i ++ ) fprintf(fp, "%02X ", rbuf[i]); fprintf(fp, "\n"); processorid++; retry = 0; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////// fprintf(fp, " <<< IA32_MC%d_MISC, ProcessorID from 0 to %d >>> \n", mc_index, MAX_PROC_ID); processorid = 0; retry = 0; while( processorid <= MAX_PROC_ID ) { param = IA32_MC_MISC_base + msr_offset; param0 = ( param & 0xFF ); param1 = ( param >> 8 ); tbuf[10] = processorid; tbuf[11] = param0; tbuf[12] = param1; comp = bic_me_xmit(slot_id, tbuf, tlen, rbuf, &rlen); check = rbuf[3]; if( (( check == 0x80 ) || ( check = 0x81 ) || ( check == 0x81 ) || ( comp != 0 )) && ( retry < MAX_RETRY ) ) { retry++; sleep(1); } else { for ( i = 0 ; i < rlen ; i ++ ) fprintf(fp, "%02X ", rbuf[i]); fprintf(fp, "\n"); processorid++; retry = 0; } } mc_index++; msr_offset+4; } fclose(fp); return 0; } int crash_dump_coreid(void) { FILE *fp = NULL; int processorid = 0, retry = 0, response = 0, comp = 1, mc_index = 0, msr_offset = 0; uint16_t param, param0, param1, cmdout; uint8_t slot_id = 1; uint8_t tbuf[256] = {0x00}; uint8_t rbuf[256] = {0x00}; uint8_t tlen = 0; uint8_t rlen = 0; uint8_t check; //for check 4th response data int i = 0; fp = fopen(CRASHDUMP_FILE, "a+"); if (!fp) { printf("File Open Fail\n"); return -1; } fprintf(fp, "\n"); fprintf(fp, "%s\n", "CPU COREID DUMP:"); fprintf(fp, "%s\n", "================"); fprintf(fp, "\n"); //PECI RdPkgConfig() "CPUID Read" fprintf(fp, "< CPUID Read >\n"); tbuf[0] = 0xB8; tbuf[1] = 0x40; tbuf[2] = 0x57; tbuf[3] = 0x01; tbuf[4] = 0x00; tbuf[5] = 0x30; tbuf[6] = 0x05; tbuf[7] = 0x05; tbuf[8] = 0xa1; tbuf[9] = 0x00; tbuf[10] = 0x00; tbuf[11] = 0x00; tbuf[12] = 0x00; tlen = 13; comp = bic_me_xmit(slot_id, tbuf, tlen, rbuf, &rlen); for ( i = 0 ; i < rlen ; i ++ ) fprintf(fp, "%02X ", rbuf[i]); fprintf(fp, "\n"); //PECI RdPkgConfig() "CPU Microcode Update Revision Read" fprintf(fp, "< CPU Microcode Update Revision Read >\n"); tbuf[11] = 0x04; comp = bic_me_xmit(slot_id, tbuf, tlen, rbuf, &rlen); for ( i = 0 ; i < rlen ; i ++ ) fprintf(fp, "%02X ", rbuf[i]); fprintf(fp, "\n"); //PECI RdPkgConfig() "MCA ERROR SOURCE LOG Read" fprintf(fp, "< MCA ERROR SOURCE LOG Read -- The socket which MCA_ERR_SRC_LOG[30]=0 is the socket that asserted IERR first >\n"); tbuf[11] = 0x05; comp = bic_me_xmit(slot_id, tbuf, tlen, rbuf, &rlen); for ( i = 0 ; i < rlen ; i ++ ) fprintf(fp, "%02X ", rbuf[i]); fprintf(fp, "\n"); //PECI RdPkgConfig() "Core ID IERR" //echo "< Core ID IERR -- determine whether a core in the failing socket asserted an IERR, completion data[3]=1 if a core caused the IERR, data[2:0] is the core ID, and save the value for matching purpose >" //ipmitool -H $1 -U $user -P $passwd -b 6 -t 0x2c raw 0x2E 0x40 0x57 0x01 0x00 $2 0x05 0x05 0xa1 0x00 0x27 0x08 0x08 fprintf(fp, "********************************************************\n"); fprintf(fp, "* IERRLOGGINGREG *\n"); fprintf(fp, "********************************************************\n"); tbuf[0] = 0xB8; tbuf[1] = 0x44; tbuf[2] = 0x57; tbuf[3] = 0x01; tbuf[4] = 0x00; tbuf[5] = 0x40; tbuf[6] = 0xA4; tbuf[7] = 0x50; tbuf[8] = 0x18; tbuf[9] = 0x00; tbuf[10] = 0x03; tlen = 11; comp = bic_me_xmit(slot_id, tbuf, tlen, rbuf, &rlen); for ( i = 0 ; i < rlen ; i ++ ) fprintf(fp, "%02X ", rbuf[i]); fprintf(fp, "\n"); fprintf(fp, "********************************************************\n"); fprintf(fp, "* MCERRLOGGINGREG *\n"); fprintf(fp, "********************************************************\n"); tbuf[0] = 0xB8; tbuf[1] = 0x44; tbuf[2] = 0x57; tbuf[3] = 0x01; tbuf[4] = 0x00; tbuf[5] = 0x40; tbuf[6] = 0xA8; tbuf[7] = 0x50; tbuf[8] = 0x18; tbuf[9] = 0x00; tbuf[10] = 0x03; tlen = 11; comp = bic_me_xmit(slot_id, tbuf, tlen, rbuf, &rlen); for ( i = 0 ; i < rlen ; i ++ ) fprintf(fp, "%02X ", rbuf[i]); fprintf(fp, "\n"); fclose(fp); return 0; } int main(int argc, char **argv) { uint8_t slot_id; uint8_t tbuf[256] = {0x00}; uint8_t rbuf[256] = {0x00}; uint8_t tlen = 0; uint8_t rlen = 0; int i; int ret; int logfd; int len; char log[128]; char temp[8]; if (argc < 4) { goto err_exit; } if (!strcmp(argv[1], "server")) { slot_id = 1; } else { goto err_exit; } if (!strcmp(argv[2], "48")) { if (!strcmp(argv[3], "msr")) { ret = crash_dump_msr(); return ret; } else if (!strcmp(argv[3], "coreid")) { ret = crash_dump_coreid(); return ret; } else { goto err_exit; } } for (i = 2; i < argc; i++) { tbuf[tlen++] = (uint8_t)strtoul(argv[i], NULL, 0); } #if 1 ret = bic_me_xmit(slot_id, tbuf, tlen, rbuf, &rlen); if (ret) { return ret; } #endif // memcpy(rbuf, tbuf, tlen); //rlen = tlen; memset(log, 0, 128); for (i = 0; i < rlen; i++) { printf("%02X ", rbuf[i]); memset(temp, 0, 8); sprintf(temp, "%02X ", rbuf[i]); strcat(log, temp); } printf("\n"); sprintf(temp, "\n"); strcat(log, temp); errno = 0; logfd = open(LOGFILE, O_CREAT | O_WRONLY); if (logfd < 0) { syslog(LOG_WARNING, "Opening a tmp file failed. errno: %d", errno); return -1; } len = write(logfd, log, strlen(log)); if (len != strlen(log)) { syslog(LOG_WARNING, "Error writing the log to the file"); return -1; } close(logfd); return 0; err_exit: print_usage_help(); return -1; }