From patchwork Mon Nov 21 22:35:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tyler Baicar X-Patchwork-Id: 9440199 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 032F86075D for ; Mon, 21 Nov 2016 22:37:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E68F128823 for ; Mon, 21 Nov 2016 22:37:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DAC9C288E7; Mon, 21 Nov 2016 22:37:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 31BF0288E2 for ; Mon, 21 Nov 2016 22:37:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755042AbcKUWgi (ORCPT ); Mon, 21 Nov 2016 17:36:38 -0500 Received: from smtp.codeaurora.org ([198.145.29.96]:39064 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754981AbcKUWge (ORCPT ); Mon, 21 Nov 2016 17:36:34 -0500 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 1AC9561514; Mon, 21 Nov 2016 22:36:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1479767793; bh=4015TuafHOZgeOlJqj4Edpbo/vP1TbqoUsyBLDunBc4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JCj9J3v44eaf/2M1BUUmC2ISDgQpq7jJhsPZJZr4cXvLIkx8hrziMpUWO9vOBWHov 9XKTG36FiltF7twcEWL1f1QocuFFIhjuNKNL1wrhYdoIQjLz1vUyeYrXjp4c1iRIFn dYtBkf1rdv8xZQNNfmR4jnekUHtdNDeIOYk/NV9Y= Received: from tbaicar-lnx.qualcomm.com (unknown [129.46.14.132]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: tbaicar@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 747EE6134D; Mon, 21 Nov 2016 22:36:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1479767786; bh=4015TuafHOZgeOlJqj4Edpbo/vP1TbqoUsyBLDunBc4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aCbh9Fqfk0cPzxQjcN/0UHAbYhq4YZMs0QtJwp7N+LdDpuBSFj0mMZ0hVQElihD1D dFOzXo1X6/RNcaW/HeaqosQrDDSwxa68nDbzKIPkiFjyVnypBnsKaODFcb50hPLasb PyX2AEmP9fR5+F+b4O8Yic31XslmICrKVoMW/nDM= DMARC-Filter: OpenDMARC Filter v1.3.1 smtp.codeaurora.org 747EE6134D Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=pass smtp.mailfrom=tbaicar@codeaurora.org From: Tyler Baicar To: marc.zyngier@arm.com, pbonzini@redhat.com, rkrcmar@redhat.com, linux@armlinux.org.uk, catalin.marinas@arm.com, will.deacon@arm.com, rjw@rjwysocki.net, lenb@kernel.org, matt@codeblueprint.co.uk, robert.moore@intel.com, lv.zheng@intel.com, nkaje@codeaurora.org, zjzhang@codeaurora.org, mark.rutland@arm.com, james.morse@arm.com, akpm@linux-foundation.org, eun.taik.lee@samsung.com, sandeepa.s.prabhu@gmail.com, shijie.huang@arm.com, rruigrok@codeaurora.org, paul.gortmaker@windriver.com, tomasz.nowicki@linaro.org, fu.wei@linaro.org, rostedt@goodmis.org, bristot@redhat.com, linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, linux-efi@vger.kernel.org, Suzuki.Poulose@arm.com, punit.agrawal@arm.com, astone@redhat.com, harba@codeaurora.org, hanjun.guo@linaro.org Cc: Tyler Baicar Subject: [PATCH V5 02/10] ras: acpi/apei: cper: generic error data entry v3 per ACPI 6.1 Date: Mon, 21 Nov 2016 15:35:55 -0700 Message-Id: <1479767763-27532-3-git-send-email-tbaicar@codeaurora.org> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1479767763-27532-1-git-send-email-tbaicar@codeaurora.org> References: <1479767763-27532-1-git-send-email-tbaicar@codeaurora.org> Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently when a RAS error is reported it is not timestamped. The ACPI 6.1 spec adds the timestamp field to the generic error data entry v3 structure. The timestamp of when the firmware generated the error is now being reported. Signed-off-by: Jonathan (Zhixiong) Zhang Signed-off-by: Richard Ruigrok Signed-off-by: Tyler Baicar Signed-off-by: Naveen Kaje Reviewed-by: James Morse --- drivers/acpi/apei/ghes.c | 14 +++++++--- drivers/firmware/efi/cper.c | 62 +++++++++++++++++++++++++++++++++++---------- include/acpi/ghes.h | 10 ++++++++ include/linux/cper.h | 12 +++++++++ 4 files changed, 80 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index b79abc5..9063d68 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -420,7 +420,8 @@ static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int int flags = -1; int sec_sev = ghes_severity(gdata->error_severity); struct cper_sec_mem_err *mem_err; - mem_err = (struct cper_sec_mem_err *)(gdata + 1); + + mem_err = acpi_hest_generic_data_payload(gdata); if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) return; @@ -450,14 +451,18 @@ static void ghes_do_proc(struct ghes *ghes, { int sev, sec_sev; struct acpi_hest_generic_data *gdata; + uuid_le sec_type; sev = ghes_severity(estatus->error_severity); apei_estatus_for_each_section(estatus, gdata) { sec_sev = ghes_severity(gdata->error_severity); - if (!uuid_le_cmp(*(uuid_le *)gdata->section_type, + sec_type = *(uuid_le *)gdata->section_type; + + if (!uuid_le_cmp(sec_type, CPER_SEC_PLATFORM_MEM)) { struct cper_sec_mem_err *mem_err; - mem_err = (struct cper_sec_mem_err *)(gdata+1); + + mem_err = acpi_hest_generic_data_payload(gdata); ghes_edac_report_mem_error(ghes, sev, mem_err); arch_apei_report_mem_error(sev, mem_err); @@ -467,7 +472,8 @@ static void ghes_do_proc(struct ghes *ghes, else if (!uuid_le_cmp(*(uuid_le *)gdata->section_type, CPER_SEC_PCIE)) { struct cper_sec_pcie *pcie_err; - pcie_err = (struct cper_sec_pcie *)(gdata+1); + + pcie_err = acpi_hest_generic_data_payload(gdata); if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE && pcie_err->validation_bits & CPER_PCIE_VALID_DEVICE_ID && diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index d425374..7e2439e 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -32,6 +32,9 @@ #include #include #include +#include +#include +#include #define INDENT_SP " " @@ -386,13 +389,37 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, pfx, pcie->bridge.secondary_status, pcie->bridge.control); } +static void cper_estatus_print_section_v300(const char *pfx, + const struct acpi_hest_generic_data_v300 *gdata) +{ + __u8 hour, min, sec, day, mon, year, century, *timestamp; + + if (gdata->validation_bits & ACPI_HEST_GEN_VALID_TIMESTAMP) { + timestamp = (__u8 *)&(gdata->time_stamp); + sec = bcd2bin(timestamp[0]); + min = bcd2bin(timestamp[1]); + hour = bcd2bin(timestamp[2]); + day = bcd2bin(timestamp[4]); + mon = bcd2bin(timestamp[5]); + year = bcd2bin(timestamp[6]); + century = bcd2bin(timestamp[7]); + printk("%stime: %7s %02d%02d-%02d-%02d %02d:%02d:%02d\n", pfx, + 0x01 & *(timestamp + 3) ? "precise" : "", century, + year, mon, day, hour, min, sec); + } +} + static void cper_estatus_print_section( - const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no) + const char *pfx, struct acpi_hest_generic_data *gdata, int sec_no) { uuid_le *sec_type = (uuid_le *)gdata->section_type; __u16 severity; char newpfx[64]; + if (acpi_hest_generic_data_version(gdata) >= 3) + cper_estatus_print_section_v300(pfx, + (const struct acpi_hest_generic_data_v300 *)gdata); + severity = gdata->error_severity; printk("%s""Error %d, type: %s\n", pfx, sec_no, cper_severity_str(severity)); @@ -403,14 +430,18 @@ static void cper_estatus_print_section( snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP); if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_GENERIC)) { - struct cper_sec_proc_generic *proc_err = (void *)(gdata + 1); + struct cper_sec_proc_generic *proc_err; + + proc_err = acpi_hest_generic_data_payload(gdata); printk("%s""section_type: general processor error\n", newpfx); if (gdata->error_data_length >= sizeof(*proc_err)) cper_print_proc_generic(newpfx, proc_err); else goto err_section_too_small; } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) { - struct cper_sec_mem_err *mem_err = (void *)(gdata + 1); + struct cper_sec_mem_err *mem_err; + + mem_err = acpi_hest_generic_data_payload(gdata); printk("%s""section_type: memory error\n", newpfx); if (gdata->error_data_length >= sizeof(struct cper_sec_mem_err_old)) @@ -419,7 +450,9 @@ static void cper_estatus_print_section( else goto err_section_too_small; } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) { - struct cper_sec_pcie *pcie = (void *)(gdata + 1); + struct cper_sec_pcie *pcie; + + pcie = acpi_hest_generic_data_payload(gdata); printk("%s""section_type: PCIe error\n", newpfx); if (gdata->error_data_length >= sizeof(*pcie)) cper_print_pcie(newpfx, pcie, gdata); @@ -438,7 +471,7 @@ void cper_estatus_print(const char *pfx, const struct acpi_hest_generic_status *estatus) { struct acpi_hest_generic_data *gdata; - unsigned int data_len, gedata_len; + unsigned int data_len; int sec_no = 0; char newpfx[64]; __u16 severity; @@ -451,12 +484,12 @@ void cper_estatus_print(const char *pfx, printk("%s""event severity: %s\n", pfx, cper_severity_str(severity)); data_len = estatus->data_length; gdata = (struct acpi_hest_generic_data *)(estatus + 1); + snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP); - while (data_len >= sizeof(*gdata)) { - gedata_len = gdata->error_data_length; + + while (data_len >= acpi_hest_generic_data_size(gdata)) { cper_estatus_print_section(newpfx, gdata, sec_no); - data_len -= gedata_len + sizeof(*gdata); - gdata = (void *)(gdata + 1) + gedata_len; + gdata = acpi_hest_generic_data_next(gdata); sec_no++; } } @@ -486,12 +519,13 @@ int cper_estatus_check(const struct acpi_hest_generic_status *estatus) return rc; data_len = estatus->data_length; gdata = (struct acpi_hest_generic_data *)(estatus + 1); - while (data_len >= sizeof(*gdata)) { - gedata_len = gdata->error_data_length; - if (gedata_len > data_len - sizeof(*gdata)) + + while (data_len >= acpi_hest_generic_data_size(gdata)) { + gedata_len = acpi_hest_generic_data_error_length(gdata); + if (gedata_len > data_len - acpi_hest_generic_data_size(gdata)) return -EINVAL; - data_len -= gedata_len + sizeof(*gdata); - gdata = (void *)(gdata + 1) + gedata_len; + data_len -= gedata_len + acpi_hest_generic_data_size(gdata); + gdata = acpi_hest_generic_data_next(gdata); } if (data_len) return -EINVAL; diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index 68f088a..56b9679 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -73,3 +73,13 @@ static inline void ghes_edac_unregister(struct ghes *ghes) { } #endif + +#define acpi_hest_generic_data_version(gdata) \ + (gdata->revision >> 8) + +static inline void *acpi_hest_generic_data_payload(struct acpi_hest_generic_data *gdata) +{ + return acpi_hest_generic_data_version(gdata) >= 3 ? + (void *)(((struct acpi_hest_generic_data_v300 *)(gdata)) + 1) : + gdata + 1; +} diff --git a/include/linux/cper.h b/include/linux/cper.h index dcacb1a..13ea41c 100644 --- a/include/linux/cper.h +++ b/include/linux/cper.h @@ -255,6 +255,18 @@ enum { #define CPER_PCIE_SLOT_SHIFT 3 +#define acpi_hest_generic_data_error_length(gdata) \ + (((struct acpi_hest_generic_data *)(gdata))->error_data_length) +#define acpi_hest_generic_data_size(gdata) \ + ((acpi_hest_generic_data_version(gdata) >= 3) ? \ + sizeof(struct acpi_hest_generic_data_v300) : \ + sizeof(struct acpi_hest_generic_data)) +#define acpi_hest_generic_data_record_size(gdata) \ + (acpi_hest_generic_data_size(gdata) + \ + acpi_hest_generic_data_error_length(gdata)) +#define acpi_hest_generic_data_next(gdata) \ + ((void *)(gdata) + acpi_hest_generic_data_record_size(gdata)) + /* * All tables and structs must be byte-packed to match CPER * specification, since the tables are provided by the system BIOS