From patchwork Thu Aug 17 17:49:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Luck X-Patchwork-Id: 9906835 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 3146F60244 for ; Thu, 17 Aug 2017 17:49:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2326E28B7A for ; Thu, 17 Aug 2017 17:49:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 17FCA28B7C; Thu, 17 Aug 2017 17:49:51 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 629B928B7A for ; Thu, 17 Aug 2017 17:49:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753787AbdHQRt1 (ORCPT ); Thu, 17 Aug 2017 13:49:27 -0400 Received: from mga07.intel.com ([134.134.136.100]:50420 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753769AbdHQRtV (ORCPT ); Thu, 17 Aug 2017 13:49:21 -0400 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga105.jf.intel.com with ESMTP; 17 Aug 2017 10:49:21 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,389,1498546800"; d="scan'208";a="124859005" Received: from agluck-desk.sc.intel.com (HELO intel.com) ([10.3.52.160]) by orsmga002.jf.intel.com with ESMTP; 17 Aug 2017 10:49:20 -0700 Date: Thu, 17 Aug 2017 10:49:20 -0700 From: "Luck, Tony" To: Punit Agrawal Cc: "Rafael J. Wysocki" , Len Brown , Boris Petkov , Tyler Baicar , "linux-acpi@vger.kernel.org" , "linux-kernel@vger.kernel.org" Subject: Re: [PATCH] ACPI/APEI: Add BERT data driver Message-ID: <20170817174920.d5jeltjcbhmhxvge@intel.com> References: <20170814165613.25561-1-tony.luck@intel.com> <87k225p1v5.fsf@e105922-lin.cambridge.arm.com> <20170815211556.nnnnbtlvorgc3ijh@intel.com> <87a82zpsd7.fsf@e105922-lin.cambridge.arm.com> <3908561D78D1C84285E8C5FCA982C28F61340302@ORSMSX114.amr.corp.intel.com> <8760dmpk30.fsf@e105922-lin.cambridge.arm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <8760dmpk30.fsf@e105922-lin.cambridge.arm.com> User-Agent: NeoMutt/20170113 (1.7.2) 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 On Thu, Aug 17, 2017 at 11:25:23AM +0100, Punit Agrawal wrote: > Though, I am OK with "table-data/BERT" as well. So I coded this up ... and it looks much better than I thought it might. A bit larger than the previous version that modified drivers/acpi/apei/bert.c. But on the plus side easy to extend if there are other ACPI tables that point at interesting data. It doesn't handle dynamic tables. That would add a lot of complexity and BERT isn't dynamic. Could be a later patch if someone has a need for it. All names negotiable. -Tony From 595562691d2747459235ddbc396949337605ac2a Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Wed, 16 Aug 2017 15:36:28 -0700 Subject: [PATCH] ACPI / sysfs: Extend ACPI sysfs to provide access to boot error region The ACPI sysfs interface provides a way to read each ACPI table from userspace via entries in /sys/firmware/acpi/tables/ The BERT table simply provides the size and address of the error record in BIOS reserved memory and users may want access to this record. In an earlier age we might have used /dev/mem to retrieve this error record, but many systems disable /dev/mem for security reasons. Extend this driver to provide read-only access to the data via a file in a new directory /sys/firmware/acpi/tables-data/ Cc: Len Brown Cc: Boris Petkov Cc: Tyler Baicar Cc: Punit Agrawal Cc: linux-acpi@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Tony Luck v3: (suggested by Punit Agrawal) extend the /sys/firmware/acpi code to provide this functionality. --- drivers/acpi/sysfs.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index e414fabf7315..b24549a012f4 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -306,11 +306,13 @@ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); /* * ACPI table sysfs I/F: * /sys/firmware/acpi/tables/ + * /sys/firmware/acpi/tables-data/ * /sys/firmware/acpi/tables/dynamic/ */ static LIST_HEAD(acpi_table_attr_list); static struct kobject *tables_kobj; +static struct kobject *tables_data_kobj; static struct kobject *dynamic_tables_kobj; static struct kobject *hotplug_kobj; @@ -325,6 +327,11 @@ struct acpi_table_attr { struct list_head node; }; +struct acpi_data_attr { + struct bin_attribute attr; + u64 addr; +}; + static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t offset, size_t count) @@ -420,6 +427,70 @@ acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context) return AE_OK; } +static ssize_t acpi_data_show(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t offset, size_t count) +{ + struct acpi_data_attr *data_attr; + void __iomem *base; + ssize_t rc; + + data_attr = container_of(bin_attr, struct acpi_data_attr, attr); + + base = acpi_os_map_memory(data_attr->addr, data_attr->attr.size); + if (!base) + return -ENOMEM; + rc = memory_read_from_buffer(buf, count, &offset, base, + data_attr->attr.size); + acpi_os_unmap_memory(base, data_attr->attr.size); + + return rc; +} + +static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr) +{ + struct acpi_table_bert *bert = th; + + if (bert->header.length < sizeof(struct acpi_table_bert) || + bert->region_length < sizeof(struct acpi_hest_generic_status)) { + kfree(data_attr); + return -EINVAL; + } + data_attr->addr = bert->address; + data_attr->attr.size = bert->region_length; + data_attr->attr.attr.name = "BERT-DATA"; + + return sysfs_create_bin_file(tables_data_kobj, &data_attr->attr); +} + +static struct acpi_data_obj { + char *name; + int (*fn)(void *, struct acpi_data_attr *); +} acpi_data_objs[] = { + { ACPI_SIG_BERT, acpi_bert_data_init }, +}; + +#define NUM_ACPI_DATA_OBJS ARRAY_SIZE(acpi_data_objs) + +static int acpi_table_data_init(struct acpi_table_header *th) +{ + struct acpi_data_attr *data_attr; + int i; + + for (i = 0; i < NUM_ACPI_DATA_OBJS; i++) { + if (ACPI_COMPARE_NAME(th->signature, acpi_data_objs[i].name)) { + data_attr = kzalloc(sizeof(*data_attr), GFP_KERNEL); + if (!data_attr) + return -ENOMEM; + sysfs_attr_init(&data_attr->attr.attr); + data_attr->attr.read = acpi_data_show; + data_attr->attr.attr.mode = 0400; + return acpi_data_objs[i].fn(th, data_attr); + } + } + return 0; +} + static int acpi_tables_sysfs_init(void) { struct acpi_table_attr *table_attr; @@ -432,6 +503,10 @@ static int acpi_tables_sysfs_init(void) if (!tables_kobj) goto err; + tables_data_kobj = kobject_create_and_add("tables-data", acpi_kobj); + if (!tables_data_kobj) + goto err_tables_data; + dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj); if (!dynamic_tables_kobj) goto err_dynamic_tables; @@ -456,13 +531,17 @@ static int acpi_tables_sysfs_init(void) return ret; } list_add_tail(&table_attr->node, &acpi_table_attr_list); + acpi_table_data_init(table_header); } kobject_uevent(tables_kobj, KOBJ_ADD); + kobject_uevent(tables_data_kobj, KOBJ_ADD); kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); return 0; err_dynamic_tables: + kobject_put(tables_data_kobj); +err_tables_data: kobject_put(tables_kobj); err: return -ENOMEM;