From patchwork Tue Aug 18 16:44:16 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fu Wei Fu X-Patchwork-Id: 52516 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f71.google.com (mail-la0-f71.google.com [209.85.215.71]) by patches.linaro.org (Postfix) with ESMTPS id 2722522EF8 for ; Tue, 18 Aug 2015 16:45:45 +0000 (UTC) Received: by lagz9 with SMTP id z9sf58963794lag.3 for ; Tue, 18 Aug 2015 09:45:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=KyLf5AFXPgCUSZqHrHfzZg7G62UsSW9bperG1B7mLzQ=; b=LV10t9m7A4SX7civa6fHsEdtcgUDzrS1viLEbH+qsVCu7zKEowUkJyGt/qF5By4St5 uD5dI2UalehekF4/fklUX7nYQXNSC8rvVCXP2/d9H3FNiccNyJfjGddnEPKETyYu5A5m 3yFmQv0ext5pJjCTnL+1gdBT7QZ3xUtNs3+kfPi84p5KzXK10TU33LA0iiyvuLHELWpV PzoI9tyX7NV5c6jFry0UfqaH+SMi29fK+HrRVeE/QypfliMLXCVNSgYEpEbNq+zFVcT+ b7lIC75+v75rX/3u8sfj+H7VLosFqSakpejaTIPoDR6ttjNt1jXV+DQmOOTcVVp6xOxf aloA== X-Gm-Message-State: ALoCoQlqq/OZKOVj8wxyW4l64cmFDsk0qcX0qRcE4pbqYJGAF8OPm57yKX7rV64ySxNLcQrEYZ74 X-Received: by 10.180.75.49 with SMTP id z17mr6533394wiv.7.1439916343757; Tue, 18 Aug 2015 09:45:43 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.43.110 with SMTP id v14ls806542lal.19.gmail; Tue, 18 Aug 2015 09:45:43 -0700 (PDT) X-Received: by 10.152.120.198 with SMTP id le6mr6969476lab.38.1439916343493; Tue, 18 Aug 2015 09:45:43 -0700 (PDT) Received: from mail-lb0-f174.google.com (mail-lb0-f174.google.com. [209.85.217.174]) by mx.google.com with ESMTPS id t5si14478628lbb.35.2015.08.18.09.45.43 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 18 Aug 2015 09:45:43 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.174 as permitted sender) client-ip=209.85.217.174; Received: by lbbpu9 with SMTP id pu9so107109043lbb.3 for ; Tue, 18 Aug 2015 09:45:43 -0700 (PDT) X-Received: by 10.112.209.106 with SMTP id ml10mr7025920lbc.112.1439916343362; Tue, 18 Aug 2015 09:45:43 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.162.200 with SMTP id yc8csp591169lbb; Tue, 18 Aug 2015 09:45:41 -0700 (PDT) X-Received: by 10.70.39.74 with SMTP id n10mr15123300pdk.57.1439916341067; Tue, 18 Aug 2015 09:45:41 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id nv14si21525798pdb.134.2015.08.18.09.45.40; Tue, 18 Aug 2015 09:45:41 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754011AbbHRQph (ORCPT + 28 others); Tue, 18 Aug 2015 12:45:37 -0400 Received: from mail-pa0-f52.google.com ([209.85.220.52]:34947 "EHLO mail-pa0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753639AbbHRQpb (ORCPT ); Tue, 18 Aug 2015 12:45:31 -0400 Received: by pacgr6 with SMTP id gr6so136360336pac.2 for ; Tue, 18 Aug 2015 09:45:31 -0700 (PDT) X-Received: by 10.68.248.102 with SMTP id yl6mr15290949pbc.66.1439916331308; Tue, 18 Aug 2015 09:45:31 -0700 (PDT) Received: from localhost.localdomain (li400-65.members.linode.com. [106.187.50.65]) by smtp.googlemail.com with ESMTPSA id sb2sm18639684pbc.32.2015.08.18.09.45.20 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 18 Aug 2015 09:45:30 -0700 (PDT) From: fu.wei@linaro.org To: linaro-acpi@lists.linaro.org, linux-kernel@vger.kernel.org, zjzhang@codeaurora.org, tony.luck@intel.com, gong.chen@intel.com, ying.huang@intel.com, tomasz.nowicki@linaro.org Cc: tekkamanninja@gmail.com, graeme.gregory@linaro.org, al.stone@linaro.org, hanjun.guo@linaro.org, jcm@redhat.com, mark.rutland@arm.com, catalin.marinas@arm.com, will.deacon@arm.com, rjw@rjwysocki.net, bp@alien8.de, matt.fleming@intel.com, "Chen, Gong" , Fu Wei Subject: [PATCH v2 1/2] acpi, apei: add Boot Error Record Table (BERT) support Date: Wed, 19 Aug 2015 00:44:16 +0800 Message-Id: <1439916257-5483-2-git-send-email-fu.wei@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1439916257-5483-1-git-send-email-fu.wei@linaro.org> References: <=fu.wei@linaro.org> <1439916257-5483-1-git-send-email-fu.wei@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: fu.wei@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.174 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Huang Ying Under normal circumstances, when a hardware error occurs, kernel will be notified via NMI, MCE or some other method, then kernel will process the error condition, report it, and recover it if possible. But sometime, the situation is so bad, so that firmware may choose to reset directly without notifying Linux kernel. Linux kernel can use the Boot Error Record Table (BERT) to get the un-notified hardware errors that occurred in a previous boot. In this patch, the error information is reported via printk. For more information about BERT, please refer to ACPI Specification version 6.0, section 18.3.1: http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf [Tony: Applied some cleanups suggested by Fu Wei] [Fu Wei: delete EXPORT_SYMBOL_GPL(bert_disable), and do some cleanups] Signed-off-by: Huang Ying Signed-off-by: Tomasz Nowicki Signed-off-by: Chen, Gong Tested-by: Jonathan (Zhixiong) Zhang Tested-by: Fu Wei Signed-off-by: Tony Luck Signed-off-by: Fu Wei --- Documentation/kernel-parameters.txt | 3 + drivers/acpi/apei/Makefile | 2 +- drivers/acpi/apei/bert.c | 162 ++++++++++++++++++++++++++++++++++++ include/acpi/apei.h | 1 + 4 files changed, 167 insertions(+), 1 deletion(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1d6f045..7c6402c 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -554,6 +554,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. bootmem_debug [KNL] Enable bootmem allocator debug messages. + bert_disable [ACPI] + Disable Boot Error Record Table (BERT) support. + bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards) bttv.radio= Most important insmod options are available as kernel args too. diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile index 5d575a9..e50573d 100644 --- a/drivers/acpi/apei/Makefile +++ b/drivers/acpi/apei/Makefile @@ -3,4 +3,4 @@ obj-$(CONFIG_ACPI_APEI_GHES) += ghes.o obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o -apei-y := apei-base.o hest.o erst.o +apei-y := apei-base.o hest.o erst.o bert.o diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c new file mode 100644 index 0000000..1426227 --- /dev/null +++ b/drivers/acpi/apei/bert.c @@ -0,0 +1,162 @@ +/* + * APEI Boot Error Record Table (BERT) support + * + * Copyright 2011 Intel Corp. + * Author: Huang Ying + * + * Under normal circumstances, when a hardware error occurs, kernel + * will be notified via NMI, MCE or some other method, then kernel + * will process the error condition, report it, and recover it if + * possible. But sometime, the situation is so bad, so that firmware + * may choose to reset directly without notifying Linux kernel. + * + * Linux kernel can use the Boot Error Record Table (BERT) to get the + * un-notified hardware errors that occurred in a previous boot. + * + * For more information about BERT, please refer to ACPI Specification + * version 4.0, section 17.3.1 + * + * This file is licensed under GPLv2. + * + */ + +#include +#include +#include +#include +#include + +#include "apei-internal.h" + +#define BERT_PFX "BERT: " + +static int bert_disable; + +static void __init bert_print_all(struct acpi_hest_generic_status *region, + unsigned int region_len) +{ + struct acpi_hest_generic_status *estatus = region; + int remain = region_len; + u32 estatus_len; + int first = 1; + + while (remain > sizeof(struct acpi_hest_generic_status)) { + /* No more error record */ + if (!estatus->block_status) + break; + + estatus_len = cper_estatus_len(estatus); + if (estatus_len < sizeof(struct acpi_hest_generic_status) || + remain < estatus_len) { + pr_err(FW_BUG BERT_PFX + "Invalid error status block with length %u\n", + estatus_len); + return; + } + + if (cper_estatus_check(estatus)) { + pr_err(FW_BUG BERT_PFX "Invalid error status block\n"); + goto next; + } + + if (first) { + pr_info(HW_ERR "Error record from previous boot:\n"); + first = 0; + } + + cper_estatus_print(KERN_INFO HW_ERR, estatus); +next: + estatus = (void *)estatus + estatus_len; + remain -= estatus_len; + } +} + +static int __init setup_bert_disable(char *str) +{ + bert_disable = 1; + + return 0; +} +__setup("bert_disable", setup_bert_disable); + +static int __init bert_check_table(struct acpi_table_bert *bert_tab) +{ + if (bert_tab->header.length < sizeof(struct acpi_table_bert)) + return -EINVAL; + if (bert_tab->region_length && + bert_tab->region_length < sizeof(struct acpi_bert_region)) + return -EINVAL; + + return 0; +} + +static int __init bert_init(void) +{ + struct acpi_hest_generic_status *bert_region; + struct acpi_table_bert *bert_tab; + unsigned int region_len; + acpi_status status; + struct resource *r; + int rc = -EINVAL; + + if (acpi_disabled) + goto out; + + if (bert_disable) { + pr_info(BERT_PFX "Boot Error Record Table (BERT) support is disabled.\n"); + goto out; + } + + status = acpi_get_table(ACPI_SIG_BERT, 0, + (struct acpi_table_header **)&bert_tab); + if (status == AE_NOT_FOUND) { + pr_err(BERT_PFX "Table is not found!\n"); + goto out; + } else if (ACPI_FAILURE(status)) { + const char *msg = acpi_format_exception(status); + + pr_err(BERT_PFX "Failed to get table, %s\n", msg); + goto out; + } + + rc = bert_check_table(bert_tab); + if (rc) { + pr_err(FW_BUG BERT_PFX "BERT table is invalid\n"); + goto out; + } + + region_len = bert_tab->region_length; + if (!region_len) { + rc = 0; + goto out; + } + + r = request_mem_region(bert_tab->address, region_len, "APEI BERT"); + if (!r) { + pr_err(BERT_PFX "Can't request iomem region <%016llx-%016llx>\n", + (unsigned long long)bert_tab->address, + (unsigned long long)bert_tab->address + region_len - 1); + rc = -EIO; + goto out; + } + + bert_region = ioremap_cache(bert_tab->address, region_len); + if (!bert_region) { + rc = -ENOMEM; + goto out_release; + } + + bert_print_all(bert_region, region_len); + + iounmap(bert_region); + +out_release: + release_mem_region(bert_tab->address, region_len); +out: + if (rc) + bert_disable = 1; + + return rc; +} + +late_initcall(bert_init); diff --git a/include/acpi/apei.h b/include/acpi/apei.h index 76284bb..284801a 100644 --- a/include/acpi/apei.h +++ b/include/acpi/apei.h @@ -23,6 +23,7 @@ extern bool ghes_disable; #else #define ghes_disable 1 #endif +extern int bert_disable; #ifdef CONFIG_ACPI_APEI void __init acpi_hest_init(void);