8bf2afa
From 973e23bf27b0b2e5021321357fc570cccea3104c 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
73649ff
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
73649ff
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
73649ff
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
8bf2afa
index d111248..b14b4c6 100644
Jesse Keating 7a32965
--- a/arch/ia64/kernel/ia64_ksyms.c
Jesse Keating 7a32965
+++ b/arch/ia64/kernel/ia64_ksyms.c
8bf2afa
@@ -9,3 +9,6 @@
8bf2afa
 EXPORT_SYMBOL(min_low_pfn);	/* defined by bootmem.c, but not exported by generic code */
8bf2afa
 EXPORT_SYMBOL(max_low_pfn);	/* defined by bootmem.c, but not exported by generic code */
8bf2afa
 #endif
8bf2afa
+
Jesse Keating 7a32965
+#include <linux/efi.h>
Jesse Keating 7a32965
+EXPORT_SYMBOL_GPL(efi_mem_type);
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
73649ff
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
73649ff
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
73649ff
index 792f9c6..3197995 100644
97686d5
--- a/arch/s390/mm/maccess.c
97686d5
+++ b/arch/s390/mm/maccess.c
73649ff
@@ -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)
73649ff
@@ -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
73649ff
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
8bf2afa
index dcc0973..99b99d5 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
8bf2afa
index 6e6c244..29cc9c8 100644
8e3ae98
--- a/drivers/char/Makefile
8e3ae98
+++ b/drivers/char/Makefile
8bf2afa
@@ -60,3 +60,5 @@ js-rtc-y = rtc.o
8e3ae98
 obj-$(CONFIG_TILE_SROM)		+= tile-srom.o
da99f20
 obj-$(CONFIG_XILLYBUS)		+= xillybus/
73649ff
 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
73649ff
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
73649ff
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__ */
73649ff
-- 
8bf2afa
2.7.4
73649ff
8bf2afa
From 23d8bd48303acda2d3a95a3e1a662784a4fa9fcd Mon Sep 17 00:00:00 2001
8771799
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
8771799
Date: Tue, 20 Sep 2016 19:39:46 +0200
8771799
Subject: [PATCH] Update of crash driver to handle CONFIG_HARDENED_USERCOPY and
8771799
 to restrict the supported architectures.
8771799
8771799
---
8771799
 drivers/char/Kconfig |  1 +
8771799
 drivers/char/crash.c | 33 ++++++++++++++++++++++++++++++---
8771799
 2 files changed, 31 insertions(+), 3 deletions(-)
8771799
8771799
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
8771799
index 99b99d5..be6a3ae 100644
8771799
--- a/drivers/char/Kconfig
8771799
+++ b/drivers/char/Kconfig
8771799
@@ -6,6 +6,7 @@ menu "Character devices"
8771799
 
8771799
 config CRASH
8771799
 	tristate "Crash Utility memory driver"
8771799
+	depends on X86_32 || X86_64 || ARM || ARM64 || PPC64 || S390
8771799
 
8771799
 source "drivers/tty/Kconfig"
8771799
 
8771799
diff --git a/drivers/char/crash.c b/drivers/char/crash.c
8771799
index 085378a..0258bf8 100644
8771799
--- a/drivers/char/crash.c
8771799
+++ b/drivers/char/crash.c
8771799
@@ -32,7 +32,7 @@
8771799
 #include <asm/types.h>
8771799
 #include <asm/crash-driver.h>
8771799
 
8771799
-#define CRASH_VERSION   "1.0"
8771799
+#define CRASH_VERSION   "1.2"
8771799
 
8771799
 /*
8771799
  *  These are the file operation functions that allow crash utility
8771799
@@ -66,6 +66,7 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
8771799
 	struct page *page;
8771799
 	u64 offset;
8771799
 	ssize_t read;
8771799
+	char *buffer = file->private_data;
8771799
 
8771799
 	offset = *poff;
8771799
 	if (offset >> PAGE_SHIFT != (offset+count-1) >> PAGE_SHIFT)
8771799
@@ -74,8 +75,12 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
8771799
 	vaddr = map_virtual(offset, &page);
8771799
 	if (!vaddr)
8771799
 		return -EFAULT;
8771799
-
8771799
-	if (copy_to_user(buf, vaddr, count)) {
8771799
+	/*
8771799
+	 * Use bounce buffer to bypass the CONFIG_HARDENED_USERCOPY
8771799
+	 * kernel text restriction.
8771799
+	*/
8771799
+	memcpy(buffer, (char *)vaddr, count);
8771799
+	if (copy_to_user(buf, buffer, count)) {
8771799
 		unmap_virtual(page);
8771799
 		return -EFAULT;
8771799
 	}
8771799
@@ -86,10 +91,32 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
8771799
 	return read;
8771799
 }
8771799
 
8771799
+static int
8771799
+crash_open(struct inode * inode, struct file * filp)
8771799
+{
8771799
+	if (!capable(CAP_SYS_RAWIO))
8771799
+		return -EPERM;
8771799
+
8771799
+	filp->private_data = (void *)__get_free_page(GFP_KERNEL);
8771799
+	if (!filp->private_data)
8771799
+		return -ENOMEM;
8771799
+
8771799
+	return 0;
8771799
+}
8771799
+
8771799
+static int
8771799
+crash_release(struct inode *inode, struct file *filp)
8771799
+{
8771799
+	free_pages((unsigned long)filp->private_data, 0);
8771799
+	return 0;
8771799
+}
8771799
+
8771799
 static struct file_operations crash_fops = {
8771799
 	.owner = THIS_MODULE,
8771799
 	.llseek = crash_llseek,
8771799
 	.read = crash_read,
8771799
+	.open = crash_open,
8771799
+	.release = crash_release,
8771799
 };
8771799
 
8771799
 static struct miscdevice crash_dev = {
8771799
-- 
8bf2afa
2.7.4
8771799
8afcc19
From: Dave Anderson <anderson@redhat.com>
8afcc19
Date: Fri, 18 Nov 2016 11:52:35 -0500
8afcc19
Cc: onestero@redhat.com
8afcc19
Subject: [PATCH v2] Restore live system crash analysis for ARM64
8afcc19
8afcc19
This v2 version simplifies the copy out of the kimage_voffset value
8afcc19
to user-space per Oleg's suggestion.
8afcc19
8afcc19
Upstream status: N/A
8afcc19
8afcc19
Test: v2 version tested successfully with a modified crash utility
8afcc19
8afcc19
The following Linux 4.6 commit breaks support for live system
8afcc19
crash analysis on ARM64:
8afcc19
8afcc19
   commit a7f8de168ace487fa7b88cb154e413cf40e87fc6
8afcc19
   Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
8afcc19
   arm64: allow kernel Image to be loaded anywhere in physical memory
8afcc19
8afcc19
The patchset drastically modified the kernel's virtual memory layout,
8afcc19
where notably the static kernel text and data image was moved from the
8afcc19
unity mapped region into the vmalloc region.  Prior to Linux 4.6,
8afcc19
the kernel's __virt_to_phys() function was this:
8afcc19
8afcc19
 #define __virt_to_phys(x)  (((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET))
8afcc19
8afcc19
When running on a live system, the crash utility could determine PAGE_OFFSET
8afcc19
by looking at the virtual addresses compiled into the vmlinux file, and
8afcc19
PHYS_OFFSET can be determined by looking at /proc/iomem.
8afcc19
8afcc19
As of Linux 4.6, it is done differently:
8afcc19
8afcc19
 #define __virt_to_phys(x) ({                                            \
8afcc19
        phys_addr_t __x = (phys_addr_t)(x);                             \
8afcc19
        __x & BIT(VA_BITS - 1) ? (__x & ~PAGE_OFFSET) + PHYS_OFFSET :   \
8afcc19
                                 (__x - kimage_voffset); })
8afcc19
8afcc19
The PAGE_OFFSET/PHYS_OFFSET section of the conditional expression is for
8afcc19
traditional unity-mapped virtual addresses, but kernel text and static
8afcc19
data requires the new "kimage_voffset" variable.  Unfortunately, the
8afcc19
contents of the new "kimage_voffset" variable is not available or
8afcc19
calculatable from a user-space perspective, even with root privileges.
8afcc19
8afcc19
At least the ARM64 developers made its contents available to modules
8afcc19
with an EXPORT_SYMBOL(kimage_voffset) declaration.  Accordingly, with
8afcc19
a modification to the /dev/crash driver to return its contents, the
8afcc19
crash utility can run on a live system.
8afcc19
8afcc19
The patch allows for architecture-specific DEV_CRASH_ARCH_DATA ioctls
8afcc19
to be created, where this is the first instance of one.
8afcc19
8afcc19
8afcc19
---
8afcc19
 arch/arm64/include/asm/crash-driver.h | 16 ++++++++++++++++
8afcc19
 drivers/char/crash.c                  | 13 ++++++++++++-
8afcc19
 2 files changed, 28 insertions(+), 1 deletion(-)
8afcc19
8afcc19
diff --git a/arch/arm64/include/asm/crash-driver.h b/arch/arm64/include/asm/crash-driver.h
8afcc19
index 43b26da..fe68e7c 100644
8afcc19
--- a/arch/arm64/include/asm/crash-driver.h
8afcc19
+++ b/arch/arm64/include/asm/crash-driver.h
8afcc19
@@ -3,4 +3,20 @@
8afcc19
 
8afcc19
 #include <asm-generic/crash-driver.h>
8afcc19
 
8afcc19
+#define DEV_CRASH_ARCH_DATA _IOR('c', 1, long)
8afcc19
+
8afcc19
+static long
8afcc19
+crash_arch_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
8afcc19
+{
8afcc19
+	extern u64 kimage_voffset;
8afcc19
+
8afcc19
+	switch (cmd)
8afcc19
+	{
8afcc19
+	case DEV_CRASH_ARCH_DATA:
8afcc19
+		return put_user(kimage_voffset, (unsigned long __user *)arg);
8afcc19
+	default:
8afcc19
+		return -EINVAL;
8afcc19
+	}
8afcc19
+}
8afcc19
+
8afcc19
 #endif /* _ARM64_CRASH_H */
8afcc19
diff --git a/drivers/char/crash.c b/drivers/char/crash.c
8afcc19
index 0258bf8..dfb767c 100644
8afcc19
--- a/drivers/char/crash.c
8afcc19
+++ b/drivers/char/crash.c
8afcc19
@@ -32,7 +32,7 @@
8afcc19
 #include <asm/types.h>
8afcc19
 #include <asm/crash-driver.h>
8afcc19
 
8afcc19
-#define CRASH_VERSION   "1.2"
8afcc19
+#define CRASH_VERSION   "1.3"
8afcc19
 
8afcc19
 /*
8afcc19
  *  These are the file operation functions that allow crash utility
8afcc19
@@ -111,10 +111,21 @@ crash_release(struct inode *inode, struct file *filp)
8afcc19
 	return 0;
8afcc19
 }
8afcc19
 
8afcc19
+static long
8afcc19
+crash_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
8afcc19
+{
8afcc19
+#ifdef DEV_CRASH_ARCH_DATA
8afcc19
+	return crash_arch_ioctl(file, cmd, arg);
8afcc19
+#else
8afcc19
+	return -EINVAL;
8afcc19
+#endif
8afcc19
+}
8afcc19
+
8afcc19
 static struct file_operations crash_fops = {
8afcc19
 	.owner = THIS_MODULE,
8afcc19
 	.llseek = crash_llseek,
8afcc19
 	.read = crash_read,
8afcc19
+	.unlocked_ioctl = crash_ioctl,
8afcc19
 	.open = crash_open,
8afcc19
 	.release = crash_release,
8afcc19
 };
8afcc19
-- 
8afcc19
1.8.3.1
8afcc19