Received: by 10.223.185.116 with SMTP id b49csp8752381wrg; Fri, 2 Mar 2018 07:22:06 -0800 (PST) X-Google-Smtp-Source: AG47ELvocfhFaAorF0uMsk0SFkbYerXiL8yqgAkRjI1XlGmamBukuLNOugFyHSEmz/zk/jLwLItT X-Received: by 10.98.144.65 with SMTP id a62mr5978394pfe.96.1520004126740; Fri, 02 Mar 2018 07:22:06 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520004126; cv=none; d=google.com; s=arc-20160816; b=WoeDOQHTW1vzHySE+hFMvuD4cormJaNgUB1qr0PjMgH2U9k1qxNbX9ybuA5dUydGNQ 67JWl6D4yeGmXuLxg/mC2042MCJe3xssOuJ/s1vt4fFXNwFZ0QR8R/qJ4NLGyGASI0nR 7bqXQclfY6uHvKtOvj069GQOpf8uqF1A90MppyoEJAiEajkyE7GtKhVb+UfISrkhIbHg dS7UBMVqLErrRa+TVudq9y+tLmGKATJQvhJUzMfXWtwe0Tma7CxwMRCKRVWS6Qtgpw3p kB/TIggTrd5ly8WAHxU1aDF3K1ABsEpzsJt288LfAnAMSb+tuQ6uVoL7dkzZxGSF2+xF JLWQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=XEDCu88xnODwPMi13cc119cfS1rsQwWk4u5WZYmj7Bc=; b=X9KGz5oBZvLSRsXaeQh3JOz9I4ODxB32QJNngA9viwo7b62IpVSKgoPCFACWRGExlz wphgXASx46SeeI8zSOC494OzzVOIfVWpMbVFc3uzYmETpa3zNp7Vom4TaxcIr71UYlui UFm9jH3llFFRaEh3DWp7z1CBbJ0tyLnANRZjfLuylvR4u2eac1G3O3wec7gSTuu/0rmm AYGubYHVDjAGRxbHSnObJZxJvj+TC+3SEiUV7qqPQwY3Od+CmrUCkeIdDBNz0iyoIYad wEvtFAfUvvkPOl7P1Ibk/LwQ0pwTzB39jRwJRvhawjjY9O09fPDIF3rRM96G9g/CgPO4 ZAqw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e61-v6si4990793plb.190.2018.03.02.07.21.51; Fri, 02 Mar 2018 07:22:06 -0800 (PST) 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; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1427528AbeCBMVl (ORCPT + 99 others); Fri, 2 Mar 2018 07:21:41 -0500 Received: from stargate.chelsio.com ([12.32.117.8]:60989 "EHLO stargate.chelsio.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1427501AbeCBMVW (ORCPT ); Fri, 2 Mar 2018 07:21:22 -0500 Received: from localhost (scalar.blr.asicdesigners.com [10.193.185.94]) by stargate.chelsio.com (8.13.8/8.13.8) with ESMTP id w22CKh2c013052; Fri, 2 Mar 2018 04:20:49 -0800 From: Rahul Lakkireddy To: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, kexec@lists.infradead.org Cc: davem@davemloft.net, ebiederm@xmission.com, akpm@linux-foundation.org, torvalds@linux-foundation.org, ganeshgr@chelsio.com, nirranjan@chelsio.com, indranil@chelsio.com, Rahul Lakkireddy Subject: [RFC 1/2] kernel/crash_core: add API to collect hardware dump in kernel panic Date: Fri, 2 Mar 2018 17:49:57 +0530 Message-Id: X-Mailer: git-send-email 2.5.3 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add API to allow drivers to register callback to collect device specific hardware/firmware dump during kernel panic. The registered callbacks will be invoked during kernel panic before moving to second kernel. Also save the dump location and size in vmcore info. The dump can be extracted using crash: crash> help -D | grep DRIVERDUMP DRIVERDUMP=(cxgb4_0000:02:00.4, ffffb131090bd000, 37782968) crash> rd ffffb131090bd000 37782968 -r hardware.log 37782968 bytes copied from 0xffffb131090bd000 to hardware.log Signed-off-by: Rahul Lakkireddy Signed-off-by: Ganesh Goudar --- include/linux/crash_core.h | 33 ++++++++++++++++++ kernel/crash_core.c | 83 +++++++++++++++++++++++++++++++++++++++++++++- kernel/kexec_core.c | 1 + 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/include/linux/crash_core.h b/include/linux/crash_core.h index b511f6d24b42..d9cc6b3346c7 100644 --- a/include/linux/crash_core.h +++ b/include/linux/crash_core.h @@ -59,6 +59,9 @@ phys_addr_t paddr_vmcoreinfo_note(void); vmcoreinfo_append_str("NUMBER(%s)=%ld\n", #name, (long)name) #define VMCOREINFO_CONFIG(name) \ vmcoreinfo_append_str("CONFIG_%s=y\n", #name) +#define VMCOREINFO_DRIVER_DUMP(name, buf, size) \ + vmcoreinfo_append_str("DRIVERDUMP=(%s, %lx, %lu)\n", \ + name, (unsigned long)buf, (unsigned long)size) extern u32 *vmcoreinfo_note; @@ -73,4 +76,34 @@ int parse_crashkernel_high(char *cmdline, unsigned long long system_ram, int parse_crashkernel_low(char *cmdline, unsigned long long system_ram, unsigned long long *crash_size, unsigned long long *crash_base); +/* Driver dump collection */ +#define CRASH_DRIVER_DUMP_NAME_LENGTH 32 + +struct crash_driver_dump_node { + struct crash_driver_dump_node __rcu *next; + struct crash_driver_dump *data; + struct notifier_block *nb; +}; + +struct crash_driver_dump_head { + struct crash_driver_dump_node __rcu *head; +}; + +#define CRASH_DRIVER_DUMP_INIT(name) { \ + .head = NULL \ +} + +#define CRASH_DRIVER_DUMP_HEAD(name) \ + struct crash_driver_dump_head name = CRASH_DRIVER_DUMP_INIT(name) \ + +struct crash_driver_dump { + char name[CRASH_DRIVER_DUMP_NAME_LENGTH]; + void *buf; + unsigned long size; +}; + +void crash_driver_dump_call_handlers(void); +int crash_driver_dump_register(struct crash_driver_dump *data, + struct notifier_block *nb); +int crash_driver_dump_unregister(struct crash_driver_dump *data); #endif /* LINUX_CRASH_CORE_H */ diff --git a/kernel/crash_core.c b/kernel/crash_core.c index 4f63597c824d..ff62713f597e 100644 --- a/kernel/crash_core.c +++ b/kernel/crash_core.c @@ -21,6 +21,64 @@ u32 *vmcoreinfo_note; /* trusted vmcoreinfo, e.g. we can make a copy in the crash memory */ static unsigned char *vmcoreinfo_data_safecopy; +/* List of driver registered callbacks to collect dumps */ +CRASH_DRIVER_DUMP_HEAD(crash_driver_dump_list); +ATOMIC_NOTIFIER_HEAD(crash_driver_dump_notifier_list); + +static int driver_dump_callback_register(struct crash_driver_dump_head *dh, + struct crash_driver_dump *data, + struct notifier_block *nb) +{ + struct crash_driver_dump_node *d, **dl; + + d = vzalloc(sizeof(*d)); + if (!d) + return -ENOMEM; + + atomic_notifier_chain_register(&crash_driver_dump_notifier_list, nb); + d->nb = nb; + d->data = data; + + dl = &dh->head; + while (*dl) + dl = &((*dl)->next); + d->next = *dl; + rcu_assign_pointer(*dl, d); + return 0; +} + +static int driver_dump_callback_unregister(struct crash_driver_dump_head *dh, + struct crash_driver_dump *data) +{ + struct atomic_notifier_head *ah = &crash_driver_dump_notifier_list; + struct crash_driver_dump_node **dl; + + dl = &dh->head; + while (*dl) { + if ((*dl)->data == data) { + atomic_notifier_chain_unregister(ah, (*dl)->nb); + rcu_assign_pointer((*dl), (*dl)->next); + vfree(*dl); + return 0; + } + dl = &((*dl)->next); + } + return -ENOENT; +} + +int crash_driver_dump_register(struct crash_driver_dump *data, + struct notifier_block *nb) +{ + return driver_dump_callback_register(&crash_driver_dump_list, data, nb); +} +EXPORT_SYMBOL(crash_driver_dump_register); + +int crash_driver_dump_unregister(struct crash_driver_dump *data) +{ + return driver_dump_callback_unregister(&crash_driver_dump_list, data); +} +EXPORT_SYMBOL(crash_driver_dump_unregister); + /* * parsing the "crashkernel" commandline * @@ -365,6 +423,30 @@ void vmcoreinfo_append_str(const char *fmt, ...) vmcoreinfo_size += r; } +void crash_driver_dump_call_handlers(void) +{ + static char driver_dump_buf[1024]; + struct crash_driver_dump_node *dl; + + dl = crash_driver_dump_list.head; + if (dl) { + atomic_notifier_call_chain(&crash_driver_dump_notifier_list, 0, + driver_dump_buf); + + /* Append to safe copy if available */ + if (vmcoreinfo_data_safecopy) + vmcoreinfo_data = vmcoreinfo_data_safecopy; + + while (dl) { + VMCOREINFO_DRIVER_DUMP(dl->data->name, dl->data->buf, + dl->data->size); + dl = dl->next; + } + + update_vmcoreinfo_note(); + } +} + /* * provide an empty default implementation here -- architecture * code may override this @@ -462,7 +544,6 @@ static int __init crash_save_vmcoreinfo_init(void) #ifdef CONFIG_HUGETLB_PAGE VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR); #endif - arch_crash_save_vmcoreinfo(); update_vmcoreinfo_note(); diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index 20fef1a38602..b86ffe24fe09 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -938,6 +938,7 @@ void __noclone __crash_kexec(struct pt_regs *regs) if (kexec_crash_image) { struct pt_regs fixed_regs; + crash_driver_dump_call_handlers(); crash_setup_regs(&fixed_regs, regs); crash_save_vmcoreinfo(); machine_crash_shutdown(&fixed_regs); -- 2.14.1