8163715
From 3fbd61fbbbfa7ae15cd3f3e2ff7a97e106be2b43 Mon Sep 17 00:00:00 2001
6a91557
From: Dave Anderson <anderson@redhat.com>
97686d5
Date: Tue, 26 Nov 2013 12:42:46 -0500
0a346ea
Subject: [PATCH] crash-driver
Jesse Keating 7a32965
6a91557
Bugzilla: N/A
6a91557
Upstream-status: Fedora mustard
Jesse Keating 7a32965
---
980c602
 arch/arm/include/asm/crash-driver.h     |   6 ++
980c602
 arch/arm64/include/asm/crash-driver.h   |   6 ++
6a91557
 arch/ia64/include/asm/crash-driver.h    |  90 ++++++++++++++++++++++
6a91557
 arch/ia64/kernel/ia64_ksyms.c           |   3 +
980c602
 arch/powerpc/include/asm/crash-driver.h |   6 ++
6a91557
 arch/s390/include/asm/crash-driver.h    |  60 +++++++++++++++
6a91557
 arch/s390/mm/maccess.c                  |   2 +
980c602
 arch/x86/include/asm/crash-driver.h     |   6 ++
6a91557
 drivers/char/Kconfig                    |   3 +
6a91557
 drivers/char/Makefile                   |   2 +
6a91557
 drivers/char/crash.c                    | 128 ++++++++++++++++++++++++++++++++
6a91557
 include/asm-generic/crash-driver.h      |  72 ++++++++++++++++++
97686d5
 12 files changed, 384 insertions(+)
980c602
 create mode 100644 arch/arm/include/asm/crash-driver.h
980c602
 create mode 100644 arch/arm64/include/asm/crash-driver.h
980c602
 create mode 100644 arch/ia64/include/asm/crash-driver.h
980c602
 create mode 100644 arch/powerpc/include/asm/crash-driver.h
980c602
 create mode 100644 arch/s390/include/asm/crash-driver.h
980c602
 create mode 100644 arch/x86/include/asm/crash-driver.h
Jesse Keating 7a32965
 create mode 100644 drivers/char/crash.c
980c602
 create mode 100644 include/asm-generic/crash-driver.h
Jesse Keating 7a32965
980c602
diff --git a/arch/arm/include/asm/crash-driver.h b/arch/arm/include/asm/crash-driver.h
0a346ea
new file mode 100644
8163715
index 0000000..06e7ae9
0a346ea
--- /dev/null
980c602
+++ b/arch/arm/include/asm/crash-driver.h
0a346ea
@@ -0,0 +1,6 @@
0a346ea
+#ifndef _ARM_CRASH_H
0a346ea
+#define _ARM_CRASH_H
0a346ea
+
980c602
+#include <asm-generic/crash-driver.h>
0a346ea
+
0a346ea
+#endif /* _ARM_CRASH_H */
980c602
diff --git a/arch/arm64/include/asm/crash-driver.h b/arch/arm64/include/asm/crash-driver.h
0a346ea
new file mode 100644
8163715
index 0000000..43b26da
0a346ea
--- /dev/null
980c602
+++ b/arch/arm64/include/asm/crash-driver.h
0a346ea
@@ -0,0 +1,6 @@
0a346ea
+#ifndef _ARM64_CRASH_H
0a346ea
+#define _ARM64_CRASH_H
0a346ea
+
980c602
+#include <asm-generic/crash-driver.h>
0a346ea
+
0a346ea
+#endif /* _ARM64_CRASH_H */
980c602
diff --git a/arch/ia64/include/asm/crash-driver.h b/arch/ia64/include/asm/crash-driver.h
Jesse Keating 7a32965
new file mode 100644
8163715
index 0000000..404bcb9
Jesse Keating 7a32965
--- /dev/null
980c602
+++ b/arch/ia64/include/asm/crash-driver.h
Jesse Keating 7a32965
@@ -0,0 +1,90 @@
Jesse Keating 7a32965
+#ifndef _ASM_IA64_CRASH_H
Jesse Keating 7a32965
+#define _ASM_IA64_CRASH_H
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+/*
980c602
+ * linux/include/asm-ia64/crash-driver.h
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * Copyright (c) 2004 Red Hat, Inc. All rights reserved.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * This program is free software; you can redistribute it and/or modify
Jesse Keating 7a32965
+ * it under the terms of the GNU General Public License as published by
Jesse Keating 7a32965
+ * the Free Software Foundation; either version 2, or (at your option)
Jesse Keating 7a32965
+ * any later version.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * This program is distributed in the hope that it will be useful,
Jesse Keating 7a32965
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
Jesse Keating 7a32965
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Jesse Keating 7a32965
+ * GNU General Public License for more details.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * You should have received a copy of the GNU General Public License
Jesse Keating 7a32965
+ * along with this program; if not, write to the Free Software
Jesse Keating 7a32965
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ */
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+#ifdef __KERNEL__
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+#include <linux/efi.h>
Jesse Keating 7a32965
+#include <linux/mm.h>
Jesse Keating 7a32965
+#include <asm/mmzone.h>
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static inline void *
Jesse Keating 7a32965
+map_virtual(u64 offset, struct page **pp)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct page *page;
Jesse Keating 7a32965
+	unsigned long pfn;
Jesse Keating 7a32965
+	u32 type;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (REGION_NUMBER(offset) == 5) {
Jesse Keating 7a32965
+		char byte;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+		if (__get_user(byte, (char *)offset) == 0)
Jesse Keating 7a32965
+			return (void *)offset;
Jesse Keating 7a32965
+		else
Jesse Keating 7a32965
+			return NULL;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
0a346ea
+	switch (type = efi_mem_type(offset))
Jesse Keating 7a32965
+	{
Jesse Keating 7a32965
+	case EFI_LOADER_CODE:
Jesse Keating 7a32965
+	case EFI_LOADER_DATA:
Jesse Keating 7a32965
+	case EFI_BOOT_SERVICES_CODE:
Jesse Keating 7a32965
+	case EFI_BOOT_SERVICES_DATA:
Jesse Keating 7a32965
+	case EFI_CONVENTIONAL_MEMORY:
Jesse Keating 7a32965
+		break;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	default:
Jesse Keating 7a32965
+		printk(KERN_INFO
0a346ea
+		    "crash memory driver: invalid memory type for %lx: %d\n",
Jesse Keating 7a32965
+			offset, type);
Jesse Keating 7a32965
+		return NULL;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	pfn = offset >> PAGE_SHIFT;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (!pfn_valid(pfn)) {
Jesse Keating 7a32965
+		printk(KERN_INFO
Jesse Keating 7a32965
+			"crash memory driver: invalid pfn: %lx )\n", pfn);
Jesse Keating 7a32965
+		return NULL;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	page = pfn_to_page(pfn);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (!page->virtual) {
Jesse Keating 7a32965
+		printk(KERN_INFO
0a346ea
+		    "crash memory driver: offset: %lx page: %lx page->virtual: NULL\n",
Jesse Keating 7a32965
+			offset, (unsigned long)page);
Jesse Keating 7a32965
+		return NULL;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return (page->virtual + (offset & (PAGE_SIZE-1)));
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
0a346ea
+static inline void unmap_virtual(struct page *page)
0a346ea
+{
Jesse Keating 7a32965
+	return;
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+#endif /* __KERNEL__ */
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+#endif /* _ASM_IA64_CRASH_H */
Jesse Keating 7a32965
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
8163715
index 0967310..e888878 100644
Jesse Keating 7a32965
--- a/arch/ia64/kernel/ia64_ksyms.c
Jesse Keating 7a32965
+++ b/arch/ia64/kernel/ia64_ksyms.c
Jesse Keating 7a32965
@@ -84,6 +84,9 @@ EXPORT_SYMBOL(ia64_save_scratch_fpregs);
Jesse Keating 7a32965
 #include <asm/unwind.h>
Jesse Keating 7a32965
 EXPORT_SYMBOL(unw_init_running);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+#include <linux/efi.h>
Jesse Keating 7a32965
+EXPORT_SYMBOL_GPL(efi_mem_type);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 #if defined(CONFIG_IA64_ESI) || defined(CONFIG_IA64_ESI_MODULE)
Jesse Keating 7a32965
 extern void esi_call_phys (void);
Jesse Keating 7a32965
 EXPORT_SYMBOL_GPL(esi_call_phys);
980c602
diff --git a/arch/powerpc/include/asm/crash-driver.h b/arch/powerpc/include/asm/crash-driver.h
Jesse Keating 7a32965
new file mode 100644
8163715
index 0000000..50092d9
Jesse Keating 7a32965
--- /dev/null
980c602
+++ b/arch/powerpc/include/asm/crash-driver.h
0a346ea
@@ -0,0 +1,6 @@
0a346ea
+#ifndef _PPC64_CRASH_H
0a346ea
+#define _PPC64_CRASH_H
Jesse Keating 7a32965
+
980c602
+#include <asm-generic/crash-driver.h>
0a346ea
+
0a346ea
+#endif /* _PPC64_CRASH_H */
980c602
diff --git a/arch/s390/include/asm/crash-driver.h b/arch/s390/include/asm/crash-driver.h
0a346ea
new file mode 100644
8163715
index 0000000..552be5e
0a346ea
--- /dev/null
980c602
+++ b/arch/s390/include/asm/crash-driver.h
0a346ea
@@ -0,0 +1,60 @@
0a346ea
+#ifndef _S390_CRASH_H
0a346ea
+#define _S390_CRASH_H
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+#ifdef __KERNEL__
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+#include <linux/mm.h>
Jesse Keating 7a32965
+#include <linux/highmem.h>
Jesse Keating 7a32965
+
0a346ea
+/*
0a346ea
+ * For swapped prefix pages get bounce buffer using xlate_dev_mem_ptr()
0a346ea
+ */
0a346ea
+static inline void *map_virtual(u64 offset, struct page **pp)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct page *page;
Jesse Keating 7a32965
+	unsigned long pfn;
Jesse Keating 7a32965
+	void *vaddr;
Jesse Keating 7a32965
+
0a346ea
+	vaddr = xlate_dev_mem_ptr(offset);
0a346ea
+	pfn = ((unsigned long) vaddr) >> PAGE_SHIFT;
0a346ea
+	if ((unsigned long) vaddr != offset)
0a346ea
+		page = pfn_to_page(pfn);
0a346ea
+	else
0a346ea
+		page = NULL;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (!page_is_ram(pfn)) {
Jesse Keating 7a32965
+		printk(KERN_INFO
Jesse Keating 7a32965
+		    "crash memory driver: !page_is_ram(pfn: %lx)\n", pfn);
Jesse Keating 7a32965
+		return NULL;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (!pfn_valid(pfn)) {
Jesse Keating 7a32965
+		printk(KERN_INFO
Jesse Keating 7a32965
+		    "crash memory driver: invalid pfn: %lx )\n", pfn);
Jesse Keating 7a32965
+		return NULL;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	*pp = page;
0a346ea
+	return vaddr;
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
0a346ea
+/*
0a346ea
+ * Free bounce buffer if necessary
0a346ea
+ */
0a346ea
+static inline void unmap_virtual(struct page *page)
0a346ea
+{
0a346ea
+	void *vaddr;
0a346ea
+
0a346ea
+	if (page) {
0a346ea
+		/*
0a346ea
+		 * Because for bounce buffers vaddr will never be 0
0a346ea
+		 * unxlate_dev_mem_ptr() will always free the bounce buffer.
0a346ea
+		 */
0a346ea
+		vaddr = (void *)(page_to_pfn(page) << PAGE_SHIFT);
0a346ea
+		unxlate_dev_mem_ptr(0, vaddr);
0a346ea
+	}
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+#endif /* __KERNEL__ */
Jesse Keating 7a32965
+
0a346ea
+#endif /* _S390_CRASH_H */
97686d5
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
8163715
index 792f9c6..3197995 100644
97686d5
--- a/arch/s390/mm/maccess.c
97686d5
+++ b/arch/s390/mm/maccess.c
8163715
@@ -201,6 +201,7 @@ void *xlate_dev_mem_ptr(phys_addr_t addr)
97686d5
 	put_online_cpus();
97686d5
 	return bounce;
97686d5
 }
97686d5
+EXPORT_SYMBOL_GPL(xlate_dev_mem_ptr);
97686d5
 
97686d5
 /*
97686d5
  * Free converted buffer for /dev/mem access (if necessary)
8163715
@@ -210,3 +211,4 @@ void unxlate_dev_mem_ptr(phys_addr_t addr, void *buf)
97686d5
 	if ((void *) addr != buf)
97686d5
 		free_page((unsigned long) buf);
97686d5
 }
97686d5
+EXPORT_SYMBOL_GPL(unxlate_dev_mem_ptr);
980c602
diff --git a/arch/x86/include/asm/crash-driver.h b/arch/x86/include/asm/crash-driver.h
0a346ea
new file mode 100644
8163715
index 0000000..fd4736e
0a346ea
--- /dev/null
980c602
+++ b/arch/x86/include/asm/crash-driver.h
0a346ea
@@ -0,0 +1,6 @@
0a346ea
+#ifndef _X86_CRASH_H
0a346ea
+#define _X86_CRASH_H
0a346ea
+
980c602
+#include <asm-generic/crash-driver.h>
0a346ea
+
0a346ea
+#endif /* _X86_CRASH_H */
8e3ae98
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
8163715
index fdb8f3e..7dd3a49 100644
8e3ae98
--- a/drivers/char/Kconfig
8e3ae98
+++ b/drivers/char/Kconfig
8e3ae98
@@ -4,6 +4,9 @@
8e3ae98
 
8e3ae98
 menu "Character devices"
8e3ae98
 
8e3ae98
+config CRASH
8e3ae98
+	tristate "Crash Utility memory driver"
8e3ae98
+
8e3ae98
 source "drivers/tty/Kconfig"
8e3ae98
 
f1193f2
 config DEVMEM
8e3ae98
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
8163715
index 55d16bf..a40ace9 100644
8e3ae98
--- a/drivers/char/Makefile
8e3ae98
+++ b/drivers/char/Makefile
8163715
@@ -61,3 +61,5 @@ js-rtc-y = rtc.o
8e3ae98
 obj-$(CONFIG_TILE_SROM)		+= tile-srom.o
da99f20
 obj-$(CONFIG_XILLYBUS)		+= xillybus/
8163715
 obj-$(CONFIG_POWERNV_OP_PANEL)	+= powernv-op-panel.o
8e3ae98
+
8e3ae98
+obj-$(CONFIG_CRASH)            += crash.o
Jesse Keating 7a32965
diff --git a/drivers/char/crash.c b/drivers/char/crash.c
Jesse Keating 7a32965
new file mode 100644
8163715
index 0000000..085378a
Jesse Keating 7a32965
--- /dev/null
Jesse Keating 7a32965
+++ b/drivers/char/crash.c
Jesse Keating 7a32965
@@ -0,0 +1,128 @@
Jesse Keating 7a32965
+/*
Jesse Keating 7a32965
+ *  linux/drivers/char/crash.c
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ *  Copyright (C) 2004  Dave Anderson <anderson@redhat.com>
Jesse Keating 7a32965
+ *  Copyright (C) 2004  Red Hat, Inc.
Jesse Keating 7a32965
+ */
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+/******************************************************************************
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ *   This program is free software; you can redistribute it and/or modify
Jesse Keating 7a32965
+ *   it under the terms of the GNU General Public License as published by
Jesse Keating 7a32965
+ *   the Free Software Foundation; either version 2, or (at your option)
Jesse Keating 7a32965
+ *   any later version.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ *   This program is distributed in the hope that it will be useful,
Jesse Keating 7a32965
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Jesse Keating 7a32965
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Jesse Keating 7a32965
+ *   GNU General Public License for more details.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ *   You should have received a copy of the GNU General Public License
Jesse Keating 7a32965
+ *   along with this program; if not, write to the Free Software
Jesse Keating 7a32965
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ *****************************************************************************/
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+#include <linux/module.h>
Jesse Keating 7a32965
+#include <linux/types.h>
Jesse Keating 7a32965
+#include <linux/miscdevice.h>
Jesse Keating 7a32965
+#include <linux/init.h>
Jesse Keating 7a32965
+#include <asm/io.h>
Jesse Keating 7a32965
+#include <asm/uaccess.h>
Jesse Keating 7a32965
+#include <asm/types.h>
980c602
+#include <asm/crash-driver.h>
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+#define CRASH_VERSION   "1.0"
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+/*
Jesse Keating 7a32965
+ *  These are the file operation functions that allow crash utility
Jesse Keating 7a32965
+ *  access to physical memory.
Jesse Keating 7a32965
+ */
Jesse Keating 7a32965
+
0a346ea
+static loff_t
Jesse Keating 7a32965
+crash_llseek(struct file * file, loff_t offset, int orig)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	switch (orig) {
Jesse Keating 7a32965
+	case 0:
Jesse Keating 7a32965
+		file->f_pos = offset;
Jesse Keating 7a32965
+		return file->f_pos;
Jesse Keating 7a32965
+	case 1:
Jesse Keating 7a32965
+		file->f_pos += offset;
Jesse Keating 7a32965
+		return file->f_pos;
Jesse Keating 7a32965
+	default:
Jesse Keating 7a32965
+		return -EINVAL;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+/*
0a346ea
+ *  Determine the page address for an address offset value,
Jesse Keating 7a32965
+ *  get a virtual address for it, and copy it out.
Jesse Keating 7a32965
+ *  Accesses must fit within a page.
Jesse Keating 7a32965
+ */
Jesse Keating 7a32965
+static ssize_t
Jesse Keating 7a32965
+crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	void *vaddr;
Jesse Keating 7a32965
+	struct page *page;
Jesse Keating 7a32965
+	u64 offset;
Jesse Keating 7a32965
+	ssize_t read;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	offset = *poff;
0a346ea
+	if (offset >> PAGE_SHIFT != (offset+count-1) >> PAGE_SHIFT)
Jesse Keating 7a32965
+		return -EINVAL;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	vaddr = map_virtual(offset, &page);
Jesse Keating 7a32965
+	if (!vaddr)
Jesse Keating 7a32965
+		return -EFAULT;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (copy_to_user(buf, vaddr, count)) {
Jesse Keating 7a32965
+		unmap_virtual(page);
Jesse Keating 7a32965
+		return -EFAULT;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+	unmap_virtual(page);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	read = count;
Jesse Keating 7a32965
+	*poff += read;
Jesse Keating 7a32965
+	return read;
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static struct file_operations crash_fops = {
Jesse Keating 7a32965
+	.owner = THIS_MODULE,
Jesse Keating 7a32965
+	.llseek = crash_llseek,
Jesse Keating 7a32965
+	.read = crash_read,
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static struct miscdevice crash_dev = {
Jesse Keating 7a32965
+	MISC_DYNAMIC_MINOR,
Jesse Keating 7a32965
+	"crash",
Jesse Keating 7a32965
+	&crash_fops
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int __init
Jesse Keating 7a32965
+crash_init(void)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	int ret;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	ret = misc_register(&crash_dev);
Jesse Keating 7a32965
+	if (ret) {
0a346ea
+		printk(KERN_ERR
Jesse Keating 7a32965
+		    "crash memory driver: cannot misc_register (MISC_DYNAMIC_MINOR)\n");
Jesse Keating 7a32965
+		goto out;
Jesse Keating 7a32965
+	}
0a346ea
+
Jesse Keating 7a32965
+	ret = 0;
Jesse Keating 7a32965
+	printk(KERN_INFO "crash memory driver: version %s\n", CRASH_VERSION);
Jesse Keating 7a32965
+out:
Jesse Keating 7a32965
+	return ret;
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static void __exit
Jesse Keating 7a32965
+crash_cleanup_module(void)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	misc_deregister(&crash_dev);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+module_init(crash_init);
Jesse Keating 7a32965
+module_exit(crash_cleanup_module);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+MODULE_LICENSE("GPL");
980c602
diff --git a/include/asm-generic/crash-driver.h b/include/asm-generic/crash-driver.h
0a346ea
new file mode 100644
8163715
index 0000000..25ab986
0a346ea
--- /dev/null
980c602
+++ b/include/asm-generic/crash-driver.h
0a346ea
@@ -0,0 +1,72 @@
0a346ea
+#ifndef __CRASH_H__
0a346ea
+#define __CRASH_H__
0a346ea
+
0a346ea
+/*
980c602
+ * include/linux/crash-driver.h
0a346ea
+ *
0a346ea
+ * Copyright (c) 2013 Red Hat, Inc. All rights reserved.
0a346ea
+ *
0a346ea
+ * This program is free software; you can redistribute it and/or modify
0a346ea
+ * it under the terms of the GNU General Public License as published by
0a346ea
+ * the Free Software Foundation; either version 2, or (at your option)
0a346ea
+ * any later version.
0a346ea
+ *
0a346ea
+ * This program is distributed in the hope that it will be useful,
0a346ea
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
0a346ea
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0a346ea
+ * GNU General Public License for more details.
0a346ea
+ *
0a346ea
+ * You should have received a copy of the GNU General Public License
0a346ea
+ * along with this program; if not, write to the Free Software
0a346ea
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
0a346ea
+ *
0a346ea
+ */
0a346ea
+
0a346ea
+#ifdef __KERNEL__
0a346ea
+
0a346ea
+#include <linux/mm.h>
0a346ea
+#include <linux/highmem.h>
0a346ea
+
0a346ea
+static inline void *
0a346ea
+map_virtual(u64 offset, struct page **pp)
0a346ea
+{
0a346ea
+	struct page *page;
0a346ea
+	unsigned long pfn;
0a346ea
+	void *vaddr;
0a346ea
+
0a346ea
+	pfn = (unsigned long)(offset >> PAGE_SHIFT);
0a346ea
+
0a346ea
+	if (!page_is_ram(pfn)) {
0a346ea
+		printk(KERN_INFO
0a346ea
+		    "crash memory driver: !page_is_ram(pfn: %lx)\n", pfn);
0a346ea
+		return NULL;
0a346ea
+	}
0a346ea
+
0a346ea
+	if (!pfn_valid(pfn)) {
0a346ea
+		printk(KERN_INFO
0a346ea
+		    "crash memory driver: invalid pfn: %lx )\n", pfn);
0a346ea
+		return NULL;
0a346ea
+	}
0a346ea
+
0a346ea
+	page = pfn_to_page(pfn);
0a346ea
+
0a346ea
+	vaddr = kmap(page);
0a346ea
+	if (!vaddr) {
0a346ea
+		printk(KERN_INFO
0a346ea
+		    "crash memory driver: pfn: %lx kmap(page: %lx) failed\n",
0a346ea
+			pfn, (unsigned long)page);
0a346ea
+		return NULL;
0a346ea
+	}
0a346ea
+
0a346ea
+	*pp = page;
0a346ea
+	return (vaddr + (offset & (PAGE_SIZE-1)));
0a346ea
+}
0a346ea
+
0a346ea
+static inline void unmap_virtual(struct page *page)
0a346ea
+{
0a346ea
+	kunmap(page);
0a346ea
+}
0a346ea
+
0a346ea
+#endif /* __KERNEL__ */
0a346ea
+
0a346ea
+#endif /* __CRASH_H__ */
8163715
-- 
8163715
2.9.2
8163715
8163715
From 7523c19e1d22fbabeaeae9520c16a78202c0eefe Mon Sep 17 00:00:00 2001
8163715
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
8163715
Date: Tue, 20 Sep 2016 19:39:46 +0200
8163715
Subject: [PATCH] Update of crash driver to handle CONFIG_HARDENED_USERCOPY and
8163715
 to restrict the supported architectures.
8163715
8163715
---
8163715
 drivers/char/Kconfig |  1 +
8163715
 drivers/char/crash.c | 33 ++++++++++++++++++++++++++++++---
8163715
 2 files changed, 31 insertions(+), 3 deletions(-)
8163715
8163715
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
8163715
index 99b99d5..be6a3ae 100644
8163715
--- a/drivers/char/Kconfig
8163715
+++ b/drivers/char/Kconfig
8163715
@@ -6,6 +6,7 @@ menu "Character devices"
8163715
 
8163715
 config CRASH
8163715
 	tristate "Crash Utility memory driver"
8163715
+	depends on X86_32 || X86_64 || ARM || ARM64 || PPC64 || S390
8163715
 
8163715
 source "drivers/tty/Kconfig"
8163715
 
8163715
diff --git a/drivers/char/crash.c b/drivers/char/crash.c
8163715
index 085378a..0258bf8 100644
8163715
--- a/drivers/char/crash.c
8163715
+++ b/drivers/char/crash.c
8163715
@@ -32,7 +32,7 @@
8163715
 #include <asm/types.h>
8163715
 #include <asm/crash-driver.h>
8163715
 
8163715
-#define CRASH_VERSION   "1.0"
8163715
+#define CRASH_VERSION   "1.2"
8163715
 
8163715
 /*
8163715
  *  These are the file operation functions that allow crash utility
8163715
@@ -66,6 +66,7 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
8163715
 	struct page *page;
8163715
 	u64 offset;
8163715
 	ssize_t read;
8163715
+	char *buffer = file->private_data;
8163715
 
8163715
 	offset = *poff;
8163715
 	if (offset >> PAGE_SHIFT != (offset+count-1) >> PAGE_SHIFT)
8163715
@@ -74,8 +75,12 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
8163715
 	vaddr = map_virtual(offset, &page);
8163715
 	if (!vaddr)
8163715
 		return -EFAULT;
8163715
-
8163715
-	if (copy_to_user(buf, vaddr, count)) {
8163715
+	/*
8163715
+	 * Use bounce buffer to bypass the CONFIG_HARDENED_USERCOPY
8163715
+	 * kernel text restriction.
8163715
+	*/
8163715
+	memcpy(buffer, (char *)vaddr, count);
8163715
+	if (copy_to_user(buf, buffer, count)) {
8163715
 		unmap_virtual(page);
8163715
 		return -EFAULT;
8163715
 	}
8163715
@@ -86,10 +91,32 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
8163715
 	return read;
8163715
 }
8163715
 
8163715
+static int
8163715
+crash_open(struct inode * inode, struct file * filp)
8163715
+{
8163715
+	if (!capable(CAP_SYS_RAWIO))
8163715
+		return -EPERM;
8163715
+
8163715
+	filp->private_data = (void *)__get_free_page(GFP_KERNEL);
8163715
+	if (!filp->private_data)
8163715
+		return -ENOMEM;
8163715
+
8163715
+	return 0;
8163715
+}
8163715
+
8163715
+static int
8163715
+crash_release(struct inode *inode, struct file *filp)
8163715
+{
8163715
+	free_pages((unsigned long)filp->private_data, 0);
8163715
+	return 0;
8163715
+}
8163715
+
8163715
 static struct file_operations crash_fops = {
8163715
 	.owner = THIS_MODULE,
8163715
 	.llseek = crash_llseek,
8163715
 	.read = crash_read,
8163715
+	.open = crash_open,
8163715
+	.release = crash_release,
8163715
 };
8163715
 
8163715
 static struct miscdevice crash_dev = {
8163715
-- 
8163715
2.9.3
8163715
5b68681
From: Dave Anderson <anderson@redhat.com>
5b68681
Date: Fri, 18 Nov 2016 11:52:35 -0500
5b68681
Cc: onestero@redhat.com
5b68681
Subject: [PATCH v2] Restore live system crash analysis for ARM64
5b68681
5b68681
This v2 version simplifies the copy out of the kimage_voffset value
5b68681
to user-space per Oleg's suggestion.
5b68681
5b68681
Upstream status: N/A
5b68681
5b68681
Test: v2 version tested successfully with a modified crash utility
5b68681
5b68681
The following Linux 4.6 commit breaks support for live system
5b68681
crash analysis on ARM64:
5b68681
5b68681
   commit a7f8de168ace487fa7b88cb154e413cf40e87fc6
5b68681
   Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
5b68681
   arm64: allow kernel Image to be loaded anywhere in physical memory
5b68681
5b68681
The patchset drastically modified the kernel's virtual memory layout,
5b68681
where notably the static kernel text and data image was moved from the
5b68681
unity mapped region into the vmalloc region.  Prior to Linux 4.6,
5b68681
the kernel's __virt_to_phys() function was this:
5b68681
5b68681
 #define __virt_to_phys(x)  (((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET))
5b68681
5b68681
When running on a live system, the crash utility could determine PAGE_OFFSET
5b68681
by looking at the virtual addresses compiled into the vmlinux file, and
5b68681
PHYS_OFFSET can be determined by looking at /proc/iomem.
5b68681
5b68681
As of Linux 4.6, it is done differently:
5b68681
5b68681
 #define __virt_to_phys(x) ({                                            \
5b68681
        phys_addr_t __x = (phys_addr_t)(x);                             \
5b68681
        __x & BIT(VA_BITS - 1) ? (__x & ~PAGE_OFFSET) + PHYS_OFFSET :   \
5b68681
                                 (__x - kimage_voffset); })
5b68681
5b68681
The PAGE_OFFSET/PHYS_OFFSET section of the conditional expression is for
5b68681
traditional unity-mapped virtual addresses, but kernel text and static
5b68681
data requires the new "kimage_voffset" variable.  Unfortunately, the
5b68681
contents of the new "kimage_voffset" variable is not available or
5b68681
calculatable from a user-space perspective, even with root privileges.
5b68681
5b68681
At least the ARM64 developers made its contents available to modules
5b68681
with an EXPORT_SYMBOL(kimage_voffset) declaration.  Accordingly, with
5b68681
a modification to the /dev/crash driver to return its contents, the
5b68681
crash utility can run on a live system.
5b68681
5b68681
The patch allows for architecture-specific DEV_CRASH_ARCH_DATA ioctls
5b68681
to be created, where this is the first instance of one.
5b68681
5b68681
5b68681
---
5b68681
 arch/arm64/include/asm/crash-driver.h | 16 ++++++++++++++++
5b68681
 drivers/char/crash.c                  | 13 ++++++++++++-
5b68681
 2 files changed, 28 insertions(+), 1 deletion(-)
5b68681
5b68681
diff --git a/arch/arm64/include/asm/crash-driver.h b/arch/arm64/include/asm/crash-driver.h
5b68681
index 43b26da..fe68e7c 100644
5b68681
--- a/arch/arm64/include/asm/crash-driver.h
5b68681
+++ b/arch/arm64/include/asm/crash-driver.h
5b68681
@@ -3,4 +3,20 @@
5b68681
 
5b68681
 #include <asm-generic/crash-driver.h>
5b68681
 
5b68681
+#define DEV_CRASH_ARCH_DATA _IOR('c', 1, long)
5b68681
+
5b68681
+static long
5b68681
+crash_arch_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
5b68681
+{
5b68681
+	extern u64 kimage_voffset;
5b68681
+
5b68681
+	switch (cmd)
5b68681
+	{
5b68681
+	case DEV_CRASH_ARCH_DATA:
5b68681
+		return put_user(kimage_voffset, (unsigned long __user *)arg);
5b68681
+	default:
5b68681
+		return -EINVAL;
5b68681
+	}
5b68681
+}
5b68681
+
5b68681
 #endif /* _ARM64_CRASH_H */
5b68681
diff --git a/drivers/char/crash.c b/drivers/char/crash.c
5b68681
index 0258bf8..dfb767c 100644
5b68681
--- a/drivers/char/crash.c
5b68681
+++ b/drivers/char/crash.c
5b68681
@@ -32,7 +32,7 @@
5b68681
 #include <asm/types.h>
5b68681
 #include <asm/crash-driver.h>
5b68681
 
5b68681
-#define CRASH_VERSION   "1.2"
5b68681
+#define CRASH_VERSION   "1.3"
5b68681
 
5b68681
 /*
5b68681
  *  These are the file operation functions that allow crash utility
5b68681
@@ -111,10 +111,21 @@ crash_release(struct inode *inode, struct file *filp)
5b68681
 	return 0;
5b68681
 }
5b68681
 
5b68681
+static long
5b68681
+crash_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
5b68681
+{
5b68681
+#ifdef DEV_CRASH_ARCH_DATA
5b68681
+	return crash_arch_ioctl(file, cmd, arg);
5b68681
+#else
5b68681
+	return -EINVAL;
5b68681
+#endif
5b68681
+}
5b68681
+
5b68681
 static struct file_operations crash_fops = {
5b68681
 	.owner = THIS_MODULE,
5b68681
 	.llseek = crash_llseek,
5b68681
 	.read = crash_read,
5b68681
+	.unlocked_ioctl = crash_ioctl,
5b68681
 	.open = crash_open,
5b68681
 	.release = crash_release,
5b68681
 };
5b68681
-- 
5b68681
1.8.3.1
5b68681