orgads / rpms / kernel

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