diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | core/Makefile.inc | 2 | ||||
-rw-r--r-- | core/pel.c | 254 | ||||
-rw-r--r-- | core/test/Makefile.check | 4 | ||||
-rw-r--r-- | core/test/run-pel.c | 81 | ||||
-rw-r--r-- | hw/fsp/fsp-elog-write.c | 239 | ||||
-rw-r--r-- | include/fsp-elog.h | 149 | ||||
-rw-r--r-- | include/pel.h | 177 |
8 files changed, 527 insertions, 380 deletions
@@ -26,6 +26,7 @@ core/test/run-mem_region_init core/test/run-mem_region_release_unused core/test/run-mem_region_release_unused_noalloc core/test/run-msg +core/test/run-pel core/test/run-trace core/test/*-gcov external/dump_trace diff --git a/core/Makefile.inc b/core/Makefile.inc index 714da3a..8b9a03b 100644 --- a/core/Makefile.inc +++ b/core/Makefile.inc @@ -6,7 +6,7 @@ CORE_OBJS += malloc.o lock.o cpu.o utils.o fdt.o opal.o interrupts.o CORE_OBJS += timebase.o opal-msg.o pci.o pci-opal.o fast-reboot.o CORE_OBJS += device.o exceptions.o trace.o affinity.o vpd.o CORE_OBJS += hostservices.o platform.o nvram.o flash-nvram.o hmi.o -CORE_OBJS += console-log.o ipmi.o time-utils.o +CORE_OBJS += console-log.o ipmi.o time-utils.o pel.o CORE=core/built-in.o $(CORE): $(CORE_OBJS:%=core/%) diff --git a/core/pel.c b/core/pel.c new file mode 100644 index 0000000..1f6d11b --- /dev/null +++ b/core/pel.c @@ -0,0 +1,254 @@ +#include <string.h> +#include <fsp-elog.h> +#include <device.h> +#include <fsp.h> +#include <pel.h> + +/* Create MTMS section for sapphire log */ +static void create_mtms_section(struct errorlog *elog_data, + char *pel_buffer, int *pel_offset) +{ + struct opal_mtms_section *mtms = (struct opal_mtms_section *) + (pel_buffer + *pel_offset); + + mtms->v6header.id = ELOG_SID_MACHINE_TYPE; + mtms->v6header.length = MTMS_SECTION_SIZE; + mtms->v6header.version = OPAL_EXT_HRD_VER; + mtms->v6header.subtype = 0; + mtms->v6header.component_id = elog_data->component_id; + + memset(mtms->model, 0x00, sizeof(mtms->model)); + memcpy(mtms->model, dt_prop_get(dt_root, "model"), OPAL_SYS_MODEL_LEN); + memset(mtms->serial_no, 0x00, sizeof(mtms->serial_no)); + + memcpy(mtms->serial_no, dt_prop_get(dt_root, "system-id"), + OPAL_SYS_SERIAL_LEN); + *pel_offset += MTMS_SECTION_SIZE; +} + +/* Create extended header section */ +static void create_extended_header_section(struct errorlog *elog_data, + char *pel_buffer, int *pel_offset) +{ + const char *opalmodel = NULL; + uint64_t extd_time; + + struct opal_extended_header_section *extdhdr = + (struct opal_extended_header_section *) + (pel_buffer + *pel_offset); + + extdhdr->v6header.id = ELOG_SID_EXTENDED_HEADER; + extdhdr->v6header.length = EXTENDED_HEADER_SECTION_SIZE; + extdhdr->v6header.version = OPAL_EXT_HRD_VER; + extdhdr->v6header.subtype = 0; + extdhdr->v6header.component_id = elog_data->component_id; + + memset(extdhdr->model, 0x00, sizeof(extdhdr->model)); + opalmodel = dt_prop_get(dt_root, "model"); + memcpy(extdhdr->model, opalmodel, OPAL_SYS_MODEL_LEN); + + memset(extdhdr->serial_no, 0x00, sizeof(extdhdr->serial_no)); + memcpy(extdhdr->serial_no, dt_prop_get(dt_root, "system-id"), + OPAL_SYS_SERIAL_LEN); + + memset(extdhdr->opal_release_version, 0x00, + sizeof(extdhdr->opal_release_version)); + memset(extdhdr->opal_subsys_version, 0x00, + sizeof(extdhdr->opal_subsys_version)); + + fsp_rtc_get_cached_tod(&extdhdr->extended_header_date, &extd_time); + extdhdr->extended_header_time = extd_time >> 32; + extdhdr->opal_symid_len = 0; + + *pel_offset += EXTENDED_HEADER_SECTION_SIZE; +} + +/* set src type */ +static void settype(struct opal_src_section *src, uint8_t src_type) +{ + char type[4]; + sprintf(type, "%02X", src_type); + memcpy(src->srcstring, type, 2); +} + +/* set SRC subsystem type */ +static void setsubsys(struct opal_src_section *src, uint8_t src_subsys) +{ + char subsys[4]; + sprintf(subsys, "%02X", src_subsys); + memcpy(src->srcstring+2, subsys, 2); +} + +/* Ser reason code of SRC */ +static void setrefcode(struct opal_src_section *src, uint16_t src_refcode) +{ + char refcode[8]; + sprintf(refcode, "%04X", src_refcode); + memcpy(src->srcstring+4, refcode, 4); +} + +/* Create SRC section of OPAL log */ +static void create_src_section(struct errorlog *elog_data, + char *pel_buffer, int *pel_offset) +{ + struct opal_src_section *src = (struct opal_src_section *) + (pel_buffer + *pel_offset); + + src->v6header.id = ELOG_SID_PRIMARY_SRC; + src->v6header.length = SRC_SECTION_SIZE; + src->v6header.version = OPAL_ELOG_VERSION; + src->v6header.subtype = OPAL_ELOG_SST; + src->v6header.component_id = elog_data->component_id; + + src->version = OPAL_SRC_SEC_VER; + src->flags = 0; + src->wordcount = OPAL_SRC_MAX_WORD_COUNT; + src->srclength = SRC_LENGTH; + settype(src, OPAL_SRC_TYPE_ERROR); + setsubsys(src, OPAL_FAILING_SUBSYSTEM); + setrefcode(src, elog_data->reason_code); + memset(src->hexwords, 0 , (8 * 4)); + src->hexwords[0] = OPAL_SRC_FORMAT; + src->hexwords[4] = elog_data->additional_info[0]; + src->hexwords[5] = elog_data->additional_info[1]; + src->hexwords[6] = elog_data->additional_info[2]; + src->hexwords[7] = elog_data->additional_info[3]; + *pel_offset += SRC_SECTION_SIZE; +} + +/* Create user header section */ +static void create_user_header_section(struct errorlog *elog_data, + char *pel_buffer, int *pel_offset) +{ + struct opal_user_header_section *usrhdr = + (struct opal_user_header_section *) + (pel_buffer + *pel_offset); + + usrhdr->v6header.id = ELOG_SID_USER_HEADER; + usrhdr->v6header.length = USER_HEADER_SECTION_SIZE; + usrhdr->v6header.version = OPAL_ELOG_VERSION; + usrhdr->v6header.subtype = OPAL_ELOG_SST; + usrhdr->v6header.component_id = elog_data->component_id; + + usrhdr->subsystem_id = elog_data->subsystem_id; + usrhdr->event_scope = 0; + usrhdr->event_severity = elog_data->event_severity; + usrhdr->event_type = elog_data->event_subtype; + + if (elog_data->elog_origin == ORG_SAPPHIRE) + usrhdr->action_flags = ERRL_ACTION_REPORT; + else + usrhdr->action_flags = ERRL_ACTION_NONE; + + *pel_offset += USER_HEADER_SECTION_SIZE; +} + +/* Create private header section */ +static void create_private_header_section(struct errorlog *elog_data, + char *pel_buffer, int *pel_offset) +{ + uint64_t ctime; + struct opal_private_header_section *privhdr = + (struct opal_private_header_section *) + pel_buffer; + + privhdr->v6header.id = ELOG_SID_PRIVATE_HEADER; + privhdr->v6header.length = PRIVATE_HEADER_SECTION_SIZE; + privhdr->v6header.version = OPAL_ELOG_VERSION; + privhdr->v6header.subtype = OPAL_ELOG_SST; + privhdr->v6header.component_id = elog_data->component_id; + privhdr->plid = elog_data->plid; + + fsp_rtc_get_cached_tod(&privhdr->create_date, &ctime); + privhdr->create_time = ctime >> 32; + privhdr->section_count = 5; + + privhdr->creator_subid_hi = 0x00; + privhdr->creator_subid_lo = 0x00; + + if (elog_data->elog_origin == ORG_SAPPHIRE) + privhdr->creator_id = OPAL_CID_SAPPHIRE; + else + privhdr->creator_id = OPAL_CID_POWERNV; + + privhdr->log_entry_id = elog_data->plid; /*entry id is updated by FSP*/ + + *pel_offset += PRIVATE_HEADER_SECTION_SIZE; +} + +static void create_user_defined_section(struct errorlog *elog_data, + char *pel_buffer, int *pel_offset) +{ + char *dump = (char *)pel_buffer + *pel_offset; + char *opal_buf = (char *)elog_data->user_data_dump; + struct opal_user_section *usrhdr; + struct elog_user_data_section *opal_usr_data; + struct opal_private_header_section *privhdr = + (struct opal_private_header_section *)pel_buffer; + int i; + + for (i = 0; i < elog_data->user_section_count; i++) { + + usrhdr = (struct opal_user_section *)dump; + opal_usr_data = (struct elog_user_data_section *)opal_buf; + + usrhdr->v6header.id = ELOG_SID_USER_DEFINED; + usrhdr->v6header.version = OPAL_ELOG_VERSION; + usrhdr->v6header.length = sizeof(struct opal_v6_header) + + opal_usr_data->size; + usrhdr->v6header.subtype = OPAL_ELOG_SST; + usrhdr->v6header.component_id = elog_data->component_id; + + memcpy(usrhdr->dump, opal_buf, opal_usr_data->size); + *pel_offset += usrhdr->v6header.length; + dump += usrhdr->v6header.length; + opal_buf += opal_usr_data->size; + privhdr->section_count++; + } +} + +static size_t pel_user_section_size(struct errorlog *elog_data) +{ + int i; + size_t total = 0; + char *opal_buf = (char *)elog_data->user_data_dump; + struct elog_user_data_section *opal_usr_data; + + for (i = 0; i < elog_data->user_section_count; i++) { + opal_usr_data = (struct elog_user_data_section *)opal_buf; + total += sizeof(struct opal_v6_header) + + opal_usr_data->size; + opal_buf += opal_usr_data->size; + } + + return total; +} + +size_t pel_size(struct errorlog *elog_data) +{ + return PEL_MIN_SIZE + pel_user_section_size(elog_data); +} + +/* Converts an OPAL errorlog into a PEL formatted log */ +int create_pel_log(struct errorlog *elog_data, char *pel_buffer, + size_t pel_buffer_size) +{ + int pel_offset = 0; + + if (pel_buffer_size < pel_size(elog_data)) { + prerror("PEL buffer too small to create record"); + return 0; + } + + memset(pel_buffer, 0, pel_buffer_size); + + create_private_header_section(elog_data, pel_buffer, &pel_offset); + create_user_header_section(elog_data, pel_buffer, &pel_offset); + create_src_section(elog_data, pel_buffer, &pel_offset); + create_extended_header_section(elog_data, pel_buffer, &pel_offset); + create_mtms_section(elog_data, pel_buffer, &pel_offset); + if (elog_data->user_section_count) + create_user_defined_section(elog_data, pel_buffer, &pel_offset); + + return pel_offset; +} diff --git a/core/test/Makefile.check b/core/test/Makefile.check index 8645001..3fe4530 100644 --- a/core/test/Makefile.check +++ b/core/test/Makefile.check @@ -1,5 +1,5 @@ # -*-Makefile-*- -CORE_TEST := core/test/run-device core/test/run-mem_region core/test/run-malloc core/test/run-malloc-speed core/test/run-mem_region_init core/test/run-mem_region_release_unused core/test/run-mem_region_release_unused_noalloc core/test/run-trace core/test/run-msg +CORE_TEST := core/test/run-device core/test/run-mem_region core/test/run-malloc core/test/run-malloc-speed core/test/run-mem_region_init core/test/run-mem_region_release_unused core/test/run-mem_region_release_unused_noalloc core/test/run-trace core/test/run-msg core/test/run-pel check: $(CORE_TEST:%=%-check) $(CORE_TEST:%=%-gcov-run) @@ -16,7 +16,7 @@ core/test/stubs.o: core/test/stubs.c $(CORE_TEST) : core/test/stubs.o -$(CORE_TEST) : % : %.c +$(CORE_TEST) : % : %.c $(HOSTCC) $(HOSTCFLAGS) -O0 -g -I include -I . -I libfdt -o $@ $< core/test/stubs.o $(CORE_TEST): % : %.d diff --git a/core/test/run-pel.c b/core/test/run-pel.c new file mode 100644 index 0000000..b7a5b26 --- /dev/null +++ b/core/test/run-pel.c @@ -0,0 +1,81 @@ +/* Copyright 2013-2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Test for our PEL record generation. Currently this doesn't actually + * test that the records we generate are correct, but it at least lets + * us run valgrind over the generation routines to check for buffer + * overflows, etc. + */ + +#include <skiboot.h> +#include <inttypes.h> +#include <assert.h> +#include <pel.h> +#include <errorlog.h> + +#define TEST_ERROR 0x1234 +#define TEST_SUBSYS 0x5678 + +DEFINE_LOG_ENTRY(TEST_ERROR, OPAL_PLATFORM_ERR_EVT, TEST_SUBSYS, + OPAL_PLATFORM_FIRMWARE, OPAL_INFO, + OPAL_NA, NULL); + +#include "../pel.c" + +struct dt_node *dt_root = NULL; +char dt_prop[] = "DUMMY DT PROP"; +const void *dt_prop_get(const struct dt_node *node __unused, const char *prop __unused) +{ + return dt_prop; +} + +int fsp_rtc_get_cached_tod(uint32_t *year_month_day, + uint64_t *hour_minute_second_millisecond) +{ + *year_month_day = 0; + *hour_minute_second_millisecond = 0; + + return 0; +} + +int main(void) +{ + char *pel_buf; + size_t size; + struct errorlog *elog; + struct opal_err_info *opal_err_info = &err_TEST_ERROR; + + elog = malloc(sizeof(struct errorlog)); + pel_buf = malloc(PEL_MIN_SIZE + 4); + assert(elog); + assert(pel_buf); + + memset(elog, 0, sizeof(struct errorlog)); + + elog->error_event_type = opal_err_info->err_type; + elog->component_id = opal_err_info->cmp_id; + elog->subsystem_id = opal_err_info->subsystem; + elog->event_severity = opal_err_info->sev; + elog->event_subtype = opal_err_info->event_subtype; + elog->reason_code = opal_err_info->reason_code; + elog->elog_origin = ORG_SAPPHIRE; + + size = pel_size(elog); + printf("PEL Size: %ld\n", size); + assert(size == create_pel_log(elog, pel_buf, size)); + + return 0; +} diff --git a/hw/fsp/fsp-elog-write.c b/hw/fsp/fsp-elog-write.c index c4c94ed..7169aa3 100644 --- a/hw/fsp/fsp-elog-write.c +++ b/hw/fsp/fsp-elog-write.c @@ -31,6 +31,7 @@ #include <errno.h> #include <fsp-elog.h> #include <timebase.h> +#include <pel.h> /* * Maximum number buffers that are pre-allocated @@ -72,7 +73,6 @@ static uint32_t elog_plid_fsp_commit = -1; enum elog_head_state elog_write_to_host_head_state = ELOG_STATE_NONE; /* Need forward declaration because of Circular dependency */ -static int create_opal_event(struct errorlog *elog_data, char *pel_buffer); static int opal_send_elog_to_fsp(void); void log_error(struct opal_err_info *e_info, void *data, uint16_t size, @@ -275,8 +275,9 @@ static void opal_commit_elog_in_host(void) (elog_write_to_host_head_state == ELOG_STATE_NONE)) { buf = list_top(&elog_write_to_host_pending, struct errorlog, link); - buf->log_size = create_opal_event(buf, - (char *)elog_write_to_host_buffer); + buf->log_size = create_pel_log(buf, + (char *)elog_write_to_host_buffer, + ELOG_WRITE_TO_HOST_BUFFER_SIZE); elog_write_to_host_head_state = ELOG_STATE_FETCHED_DATA; opal_update_pending_evt(OPAL_EVENT_ERROR_LOG_AVAIL, OPAL_EVENT_ERROR_LOG_AVAIL); @@ -386,8 +387,9 @@ static int opal_send_elog_to_fsp(void) head = list_top(&elog_write_to_fsp_pending, struct errorlog, link); elog_plid_fsp_commit = head->plid; - head->log_size = create_opal_event(head, - (char *)elog_write_to_fsp_buffer); + head->log_size = create_pel_log(head, + (char *)elog_write_to_fsp_buffer, + ELOG_WRITE_TO_FSP_BUFFER_SIZE); rc = fsp_opal_elog_write(head->log_size); unlock(&elog_write_lock); return rc; @@ -403,8 +405,9 @@ static int opal_push_logs_sync_to_fsp(struct errorlog *buf) int rc = OPAL_SUCCESS; lock(&elog_panic_write_lock); - opal_elog_size = create_opal_event(buf, - (char *)elog_panic_write_buffer); + opal_elog_size = create_pel_log(buf, + (char *)elog_panic_write_buffer, + ELOG_PANIC_WRITE_BUFFER_SIZE); elog_msg = fsp_mkmsg(FSP_CMD_CREATE_ERRLOG, 3, opal_elog_size, 0, PSI_DMA_ELOG_PANIC_WRITE_BUF); @@ -492,228 +495,6 @@ int opal_elog_update_user_dump(struct errorlog *buf, unsigned char *data, return 0; } -/* Create MTMS section for sapphire log */ -static void create_mtms_section(struct errorlog *elog_data, - char *pel_buffer, int *pel_offset) -{ - struct opal_mtms_section *mtms = (struct opal_mtms_section *) - (pel_buffer + *pel_offset); - - mtms->v6header.id = ELOG_SID_MACHINE_TYPE; - mtms->v6header.length = MTMS_SECTION_SIZE; - mtms->v6header.version = OPAL_EXT_HRD_VER; - mtms->v6header.subtype = 0; - mtms->v6header.component_id = elog_data->component_id; - - memset(mtms->model, 0x00, sizeof(mtms->model)); - memcpy(mtms->model, dt_prop_get(dt_root, "model"), OPAL_SYS_MODEL_LEN); - memset(mtms->serial_no, 0x00, sizeof(mtms->serial_no)); - - memcpy(mtms->serial_no, dt_prop_get(dt_root, "system-id"), - OPAL_SYS_SERIAL_LEN); - *pel_offset += MTMS_SECTION_SIZE; -} - -/* Create extended header section */ -static void create_extended_header_section(struct errorlog *elog_data, - char *pel_buffer, int *pel_offset) -{ - const char *opalmodel = NULL; - uint64_t extd_time; - - struct opal_extended_header_section *extdhdr = - (struct opal_extended_header_section *) - (pel_buffer + *pel_offset); - - extdhdr->v6header.id = ELOG_SID_EXTENDED_HEADER; - extdhdr->v6header.length = EXTENDED_HEADER_SECTION_SIZE; - extdhdr->v6header.version = OPAL_EXT_HRD_VER; - extdhdr->v6header.subtype = 0; - extdhdr->v6header.component_id = elog_data->component_id; - - memset(extdhdr->model, 0x00, sizeof(extdhdr->model)); - opalmodel = dt_prop_get(dt_root, "model"); - memcpy(extdhdr->model, opalmodel, OPAL_SYS_MODEL_LEN); - - memset(extdhdr->serial_no, 0x00, sizeof(extdhdr->serial_no)); - memcpy(extdhdr->serial_no, dt_prop_get(dt_root, "system-id"), - OPAL_SYS_SERIAL_LEN); - - memset(extdhdr->opal_release_version, 0x00, - sizeof(extdhdr->opal_release_version)); - memset(extdhdr->opal_subsys_version, 0x00, - sizeof(extdhdr->opal_subsys_version)); - - fsp_rtc_get_cached_tod(&extdhdr->extended_header_date, &extd_time); - extdhdr->extended_header_time = extd_time >> 32; - extdhdr->opal_symid_len = 0; - memset(extdhdr->opalsymid, 0x00, sizeof(extdhdr->opalsymid)); - - *pel_offset += EXTENDED_HEADER_SECTION_SIZE; -} - -/* set src type */ -static void settype(struct opal_src_section *src, uint8_t src_type) -{ - char type[4]; - sprintf(type, "%02X", src_type); - memcpy(src->srcstring, type, 2); -} - -/* set SRC subsystem type */ -static void setsubsys(struct opal_src_section *src, uint8_t src_subsys) -{ - char subsys[4]; - sprintf(subsys, "%02X", src_subsys); - memcpy(src->srcstring+2, subsys, 2); -} - -/* Ser reason code of SRC */ -static void setrefcode(struct opal_src_section *src, uint16_t src_refcode) -{ - char refcode[8]; - sprintf(refcode, "%04X", src_refcode); - memcpy(src->srcstring+4, refcode, 4); -} - -/* Create SRC section of OPAL log */ -static void create_src_section(struct errorlog *elog_data, - char *pel_buffer, int *pel_offset) -{ - struct opal_src_section *src = (struct opal_src_section *) - (pel_buffer + *pel_offset); - - src->v6header.id = ELOG_SID_PRIMARY_SRC; - src->v6header.length = SRC_SECTION_SIZE; - src->v6header.version = OPAL_ELOG_VERSION; - src->v6header.subtype = OPAL_ELOG_SST; - src->v6header.component_id = elog_data->component_id; - - src->version = OPAL_SRC_SEC_VER; - src->flags = 0; - src->wordcount = OPAL_SRC_MAX_WORD_COUNT; - src->srclength = SRC_LENGTH; - settype(src, OPAL_SRC_TYPE_ERROR); - setsubsys(src, OPAL_FAILING_SUBSYSTEM); - setrefcode(src, elog_data->reason_code); - memset(src->hexwords, 0 , (8 * 4)); - src->hexwords[0] = OPAL_SRC_FORMAT; - src->hexwords[4] = elog_data->additional_info[0]; - src->hexwords[5] = elog_data->additional_info[1]; - src->hexwords[6] = elog_data->additional_info[2]; - src->hexwords[7] = elog_data->additional_info[3]; - *pel_offset += SRC_SECTION_SIZE; -} - -/* Create user header section */ -static void create_user_header_section(struct errorlog *elog_data, - char *pel_buffer, int *pel_offset) -{ - struct opal_user_header_section *usrhdr = - (struct opal_user_header_section *) - (pel_buffer + *pel_offset); - - usrhdr->v6header.id = ELOG_SID_USER_HEADER; - usrhdr->v6header.length = USER_HEADER_SECTION_SIZE; - usrhdr->v6header.version = OPAL_ELOG_VERSION; - usrhdr->v6header.subtype = OPAL_ELOG_SST; - usrhdr->v6header.component_id = elog_data->component_id; - - usrhdr->subsystem_id = elog_data->subsystem_id; - usrhdr->event_scope = 0; - usrhdr->event_severity = elog_data->event_severity; - usrhdr->event_type = elog_data->event_subtype; - - if (elog_data->elog_origin == ORG_SAPPHIRE) - usrhdr->action_flags = ERRL_ACTION_REPORT; - else - usrhdr->action_flags = ERRL_ACTION_NONE; - - *pel_offset += USER_HEADER_SECTION_SIZE; -} - -/* Create private header section */ -static void create_private_header_section(struct errorlog *elog_data, - char *pel_buffer, int *pel_offset) -{ - uint64_t ctime; - struct opal_private_header_section *privhdr = - (struct opal_private_header_section *) - pel_buffer; - - privhdr->v6header.id = ELOG_SID_PRIVATE_HEADER; - privhdr->v6header.length = PRIVATE_HEADER_SECTION_SIZE; - privhdr->v6header.version = OPAL_ELOG_VERSION; - privhdr->v6header.subtype = OPAL_ELOG_SST; - privhdr->v6header.component_id = elog_data->component_id; - privhdr->plid = elog_data->plid; - - fsp_rtc_get_cached_tod(&privhdr->create_date, &ctime); - privhdr->create_time = ctime >> 32; - privhdr->section_count = 5; - - privhdr->creator_subid_hi = 0x00; - privhdr->creator_subid_lo = 0x00; - - if (elog_data->elog_origin == ORG_SAPPHIRE) - privhdr->creator_id = OPAL_CID_SAPPHIRE; - else - privhdr->creator_id = OPAL_CID_POWERNV; - - privhdr->log_entry_id = elog_data->plid; /*entry id is updated by FSP*/ - - *pel_offset += PRIVATE_HEADER_SECTION_SIZE; -} - -static void create_user_defined_section(struct errorlog *elog_data, - char *pel_buffer, int *pel_offset) -{ - char *dump = (char *)pel_buffer + *pel_offset; - char *opal_buf = (char *)elog_data->user_data_dump; - struct opal_user_section *usrhdr; - struct elog_user_data_section *opal_usr_data; - struct opal_private_header_section *privhdr = - (struct opal_private_header_section *)pel_buffer; - int i; - - for (i = 0; i < elog_data->user_section_count; i++) { - - usrhdr = (struct opal_user_section *)dump; - opal_usr_data = (struct elog_user_data_section *)opal_buf; - - usrhdr->v6header.id = ELOG_SID_USER_DEFINED; - usrhdr->v6header.version = OPAL_ELOG_VERSION; - usrhdr->v6header.length = sizeof(struct opal_v6_header) + - opal_usr_data->size; - usrhdr->v6header.subtype = OPAL_ELOG_SST; - usrhdr->v6header.component_id = elog_data->component_id; - - memcpy(usrhdr->dump, opal_buf, opal_usr_data->size); - *pel_offset += usrhdr->v6header.length; - dump += usrhdr->v6header.length; - opal_buf += opal_usr_data->size; - privhdr->section_count++; - } -} - -/* Create all require section of PEL log and write to TCE buffer */ -static int create_opal_event(struct errorlog *elog_data, char *pel_buffer) -{ - int pel_offset = 0; - - memset(pel_buffer, 0, PSI_DMA_ELOG_WR_TO_HOST_BUF_SZ); - - create_private_header_section(elog_data, pel_buffer, &pel_offset); - create_user_header_section(elog_data, pel_buffer, &pel_offset); - create_src_section(elog_data, pel_buffer, &pel_offset); - create_extended_header_section(elog_data, pel_buffer, &pel_offset); - create_mtms_section(elog_data, pel_buffer, &pel_offset); - if (elog_data->user_section_count) - create_user_defined_section(elog_data, pel_buffer, &pel_offset); - - return pel_offset; -} - /* Pre-allocate memory for writing error log to FSP */ static int init_elog_write_free_list(uint32_t num_entries) { diff --git a/include/fsp-elog.h b/include/fsp-elog.h index fa76219..abf3972 100644 --- a/include/fsp-elog.h +++ b/include/fsp-elog.h @@ -15,6 +15,7 @@ */ #include <opal.h> #include <errorlog.h> +#include <pel.h> #ifndef __ELOG_H #define __ELOG_H @@ -192,154 +193,6 @@ enum opal_reasoncode { = OPAL_FP | 0x10, }; -/* Data Structures for PEL data. */ - -#define PRIVATE_HEADER_SECTION_SIZE 48 -#define USER_HEADER_SECTION_SIZE 24 -#define SRC_SECTION_SIZE 80 -#define SRC_SUBSECTION_SIZE 4 -#define SRC_LENGTH 72 -#define OPAL_MAX_SRC_BYTES 32 -#define EXTENDED_HEADER_SECTION_SIZE 76 -#define MTMS_SECTION_SIZE 28 -#define IO_EVENT_SECTION_SIZE 16 - -#define OPAL_ELOG_VERSION 1 -#define OPAL_ELOG_SST 0 -#define OPAL_SRC_MAX_WORD_COUNT 8 - -#define OPAL_SRC_FORMAT 0x80 -#define OPAL_FAILING_SUBSYSTEM 0x82 - -#define OPAL_SYS_MODEL_LEN 8 -#define OPAL_SYS_SERIAL_LEN 12 -#define OPAL_VER_LEN 16 -#define OPAL_SYMPID_LEN 80 -#define OPAL_RC_NONE 0 - -#define OPAL_IO_MAX_RPC_DATA 216 -#define OPAL_SRC_SEC_VER 0x02 -#define OPAL_EXT_HRD_VER 0x01 - -/* Error log reporting action */ -#define ERRL_ACTION_REPORT 0x2000 -#define ERRL_ACTION_NONE 0x0000 - -enum elogSectionId { - ELOG_SID_PRIVATE_HEADER = 0x5048, /* PH */ - ELOG_SID_USER_HEADER = 0x5548, /* UH */ - ELOG_SID_EXTENDED_HEADER = 0x4548, /* EH */ - ELOG_SID_PRIMARY_SRC = 0x5053, /* PS */ - ELOG_SID_MACHINE_TYPE = 0x4D54, /* MT */ - ELOG_SID_SECONDARY_SRC = 0x5353, /* SS */ - ELOG_SID_CALL_HOME = 0x4348, /* CH */ - ELOG_SID_DUMP_LOCATOR = 0x4448, /* DH */ - ELOG_SID_SOFTWARE_ERROR = 0x5357, /* SW */ - ELOG_SID_PARTITION = 0x4C50, /* LP */ - ELOG_SID_LOGICAL_RESOURCE = 0x4C52, /* LR */ - ELOG_SID_HMC_ID = 0x484D, /* HM */ - ELOG_SID_EPOW = 0x4550, /* EP */ - ELOG_SID_IO_EVENT = 0x4945, /* IE */ - ELOG_SID_MFG_INFORMATION = 0x4D49, /* MI */ - ELOG_SID_USER_DEFINED = 0x5544 /* UD */ -}; - -struct opal_v6_header { - enum elogSectionId id:16; /* section id */ - uint16_t length; /* section length */ - uint8_t version; /* section version */ - uint8_t subtype; /* section sub-type id */ - uint16_t component_id; /* component id of section creator */ -}; - -/* opal_srctype */ -#define OPAL_SRC_TYPE_ERROR 0xBB - -#define OPAL_CID_SAPPHIRE 'K' /* creator ID for sapphire log */ -#define OPAL_CID_POWERNV 'P' /* creator ID for powernv log */ - -/* Origin of error, elog_origin */ -#define ORG_SAPPHIRE 1 -#define ORG_POWERNV 2 - -/* MAX time for error log commit */ -#define ERRORLOG_TIMEOUT_INTERVAL 180 - -/*struct opal_private head section_ */ -struct opal_private_header_section { - - struct opal_v6_header v6header; - uint32_t create_date; - uint32_t create_time; - uint32_t commit_date; - uint32_t commit_time; - - uint32_t creator_id:8; /* subsystem component id */ - uint32_t reserved_0:16; - uint32_t section_count:8; /* number of sections in log */ - uint32_t reserved_1; - uint32_t creator_subid_hi; - uint32_t creator_subid_lo; - uint32_t plid; /* platform log id */ - uint32_t log_entry_id; /* Unique log entry id */ -}; - -/* opal user header section */ -struct opal_user_header_section { - - struct opal_v6_header v6header; - - uint8_t subsystem_id; /* subsystem id */ - uint8_t event_scope; - uint8_t event_severity; - uint8_t event_type; /* error/event severity */ - - uint32_t reserved_0; - uint16_t reserved_1; - uint16_t action_flags; /* error action code */ - uint32_t reserved_2; -}; - -struct opal_src_section { - struct opal_v6_header v6header; - uint8_t version; - uint8_t flags; - uint8_t reserved_0; - uint8_t wordcount; - uint16_t reserved_1; - uint16_t srclength; - uint32_t hexwords[OPAL_SRC_MAX_WORD_COUNT]; - char srcstring[OPAL_MAX_SRC_BYTES]; -}; - -struct opal_extended_header_section { - struct opal_v6_header v6header; - char model[OPAL_SYS_MODEL_LEN]; - char serial_no[OPAL_SYS_SERIAL_LEN]; - char opal_release_version[OPAL_VER_LEN]; - char opal_subsys_version[OPAL_VER_LEN]; - uint16_t reserved_0; - uint32_t extended_header_date; - uint32_t extended_header_time; - uint16_t reserved_1; - uint8_t reserved_2; - uint8_t opal_symid_len; - char opalsymid[OPAL_SYMPID_LEN]; -}; - -/* opal MTMS section */ -struct opal_mtms_section { - struct opal_v6_header v6header; - char model[OPAL_SYS_MODEL_LEN]; - char serial_no[OPAL_SYS_SERIAL_LEN]; -}; - -/* User defined section */ -struct opal_user_section { - struct opal_v6_header v6header; - char dump[1]; -}; - struct opal_err_info { uint32_t reason_code; uint8_t err_type; diff --git a/include/pel.h b/include/pel.h new file mode 100644 index 0000000..6c06de8 --- /dev/null +++ b/include/pel.h @@ -0,0 +1,177 @@ +/* Copyright 2013-2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __PEL_H +#define __PEL_H + +/* Data Structures for PEL data. */ + +#define PRIVATE_HEADER_SECTION_SIZE 48 +#define USER_HEADER_SECTION_SIZE 24 +#define SRC_SECTION_SIZE 80 +#define SRC_SUBSECTION_SIZE 4 +#define SRC_LENGTH 72 +#define OPAL_MAX_SRC_BYTES 32 +#define EXTENDED_HEADER_SECTION_SIZE 76 +#define MTMS_SECTION_SIZE 28 +#define IO_EVENT_SECTION_SIZE 16 + +#define OPAL_ELOG_VERSION 1 +#define OPAL_ELOG_SST 0 +#define OPAL_SRC_MAX_WORD_COUNT 8 + +#define OPAL_SRC_FORMAT 0x80 +#define OPAL_FAILING_SUBSYSTEM 0x82 + +#define OPAL_SYS_MODEL_LEN 8 +#define OPAL_SYS_SERIAL_LEN 12 +#define OPAL_VER_LEN 16 +#define OPAL_SYMPID_LEN 80 +#define OPAL_RC_NONE 0 + +#define OPAL_IO_MAX_RPC_DATA 216 +#define OPAL_SRC_SEC_VER 0x02 +#define OPAL_EXT_HRD_VER 0x01 + +/* Error log reporting action */ +#define ERRL_ACTION_REPORT 0x2000 +#define ERRL_ACTION_NONE 0x0000 + +enum elogSectionId { + ELOG_SID_PRIVATE_HEADER = 0x5048, /* PH */ + ELOG_SID_USER_HEADER = 0x5548, /* UH */ + ELOG_SID_EXTENDED_HEADER = 0x4548, /* EH */ + ELOG_SID_PRIMARY_SRC = 0x5053, /* PS */ + ELOG_SID_MACHINE_TYPE = 0x4D54, /* MT */ + ELOG_SID_SECONDARY_SRC = 0x5353, /* SS */ + ELOG_SID_CALL_HOME = 0x4348, /* CH */ + ELOG_SID_DUMP_LOCATOR = 0x4448, /* DH */ + ELOG_SID_SOFTWARE_ERROR = 0x5357, /* SW */ + ELOG_SID_PARTITION = 0x4C50, /* LP */ + ELOG_SID_LOGICAL_RESOURCE = 0x4C52, /* LR */ + ELOG_SID_HMC_ID = 0x484D, /* HM */ + ELOG_SID_EPOW = 0x4550, /* EP */ + ELOG_SID_IO_EVENT = 0x4945, /* IE */ + ELOG_SID_MFG_INFORMATION = 0x4D49, /* MI */ + ELOG_SID_USER_DEFINED = 0x5544 /* UD */ +}; + + +struct opal_v6_header { + enum elogSectionId id:16; /* section id */ + uint16_t length; /* section length */ + uint8_t version; /* section version */ + uint8_t subtype; /* section sub-type id */ + uint16_t component_id; /* component id of section creator */ +}; + +/* opal_srctype */ +#define OPAL_SRC_TYPE_ERROR 0xBB + +#define OPAL_CID_SAPPHIRE 'K' /* creator ID for sapphire log */ +#define OPAL_CID_POWERNV 'P' /* creator ID for powernv log */ + +/* Origin of error, elog_origin */ +#define ORG_SAPPHIRE 1 +#define ORG_POWERNV 2 + +/* MAX time for error log commit */ +#define ERRORLOG_TIMEOUT_INTERVAL 180 + +/*struct opal_private head section_ */ +struct opal_private_header_section { + + struct opal_v6_header v6header; + uint32_t create_date; + uint32_t create_time; + uint32_t commit_date; + uint32_t commit_time; + + uint32_t creator_id:8; /* subsystem component id */ + uint32_t reserved_0:16; + uint32_t section_count:8; /* number of sections in log */ + uint32_t reserved_1; + uint32_t creator_subid_hi; + uint32_t creator_subid_lo; + uint32_t plid; /* platform log id */ + uint32_t log_entry_id; /* Unique log entry id */ +}; + +/* opal user header section */ +struct opal_user_header_section { + + struct opal_v6_header v6header; + + uint8_t subsystem_id; /* subsystem id */ + uint8_t event_scope; + uint8_t event_severity; + uint8_t event_type; /* error/event severity */ + + uint32_t reserved_0; + uint16_t reserved_1; + uint16_t action_flags; /* error action code */ + uint32_t reserved_2; +}; + +struct opal_src_section { + struct opal_v6_header v6header; + uint8_t version; + uint8_t flags; + uint8_t reserved_0; + uint8_t wordcount; + uint16_t reserved_1; + uint16_t srclength; + uint32_t hexwords[OPAL_SRC_MAX_WORD_COUNT]; + char srcstring[OPAL_MAX_SRC_BYTES]; +}; + +struct opal_extended_header_section { + struct opal_v6_header v6header; + char model[OPAL_SYS_MODEL_LEN]; + char serial_no[OPAL_SYS_SERIAL_LEN]; + char opal_release_version[OPAL_VER_LEN]; + char opal_subsys_version[OPAL_VER_LEN]; + uint16_t reserved_0; + uint32_t extended_header_date; + uint32_t extended_header_time; + uint16_t reserved_1; + uint8_t reserved_2; + uint8_t opal_symid_len; + char opalsymid[OPAL_SYMPID_LEN]; +}; + +/* opal MTMS section */ +struct opal_mtms_section { + struct opal_v6_header v6header; + char model[OPAL_SYS_MODEL_LEN]; + char serial_no[OPAL_SYS_SERIAL_LEN]; +}; + +/* User defined section */ +struct opal_user_section { + struct opal_v6_header v6header; + char dump[1]; +}; + +/* The minimum size of a PEL record */ +#define PEL_MIN_SIZE (PRIVATE_HEADER_SECTION_SIZE + USER_HEADER_SECTION_SIZE \ + + SRC_SECTION_SIZE + EXTENDED_HEADER_SECTION_SIZE \ + + MTMS_SECTION_SIZE) + +size_t pel_size(struct errorlog *elog_data); +int create_pel_log(struct errorlog *elog_data, char *pel_buffer, + size_t pel_buffer_size); + +#endif |