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