1 /* 2 * Crasher module for kdump testing 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 * 18 * Copyright IBM Corporation 2007 19 * 20 */ 21 22 #include <linux/module.h> 23 #include <linux/kernel.h> 24 #include <linux/init.h> 25 #include <linux/proc_fs.h> 26 #include <linux/spinlock.h> 27 #include <asm/uaccess.h> 28 #include <linux/version.h> 29 #include <linux/uaccess.h> 30 31 MODULE_LICENSE("GPL"); 32 33 int crasher_init(void); 34 void crasher_exit(void); 35 module_init(crasher_init); 36 module_exit(crasher_exit); 37 38 #define CRASH "crasher" /* name of /proc entry file */ 39 40 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) 41 static int crasher_read(char *buf, char **start, off_t offset, int len, 42 int *eof, void *data) 43 #else 44 static ssize_t crasher_read(struct file *file, char __user *buf, size_t len, 45 loff_t *offset) 46 #endif 47 { 48 return (sprintf(buf, "\n")); 49 } 50 51 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) 52 static int crasher_write(struct file *file, const char *buffer, 53 unsigned long count, void *data) 54 #else 55 static ssize_t crasher_write(struct file *file, const char __user *buffer, 56 size_t count, loff_t *data) 57 #endif 58 { 59 char value, *a; 60 DEFINE_SPINLOCK(mylock); 61 62 /* grab the first byte the user gave us, ignore the rest */ 63 if (copy_from_user(&value, buffer, 1)) 64 return -EFAULT; 65 66 switch (value) { 67 case '0': /* panic the system */ 68 panic("KDUMP test panic\n"); 69 break; 70 71 case '1': /* BUG() test */ 72 BUG(); 73 break; 74 75 case '2': /* panic_on_oops test */ 76 a = 0; 77 a[1] = 'A'; 78 break; 79 80 case '3': /* hang w/double spinlock */ 81 spin_lock_irq(&mylock); 82 spin_lock_irq(&mylock); 83 break; 84 85 default: 86 printk("crasher: Bad command\n"); 87 } 88 89 return count; /* tell the user we read all his data, 90 somtimes white lies are ok */ 91 } 92 93 /* create a directory in /proc and a debug file in the new directory */ 94 95 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) 96 static const struct file_operations crasher_proc_fops = { 97 .owner = THIS_MODULE, 98 .read = crasher_read, 99 .write = crasher_write, 100 }; 101 #endif 102 103 int crasher_init(void) 104 { 105 struct proc_dir_entry *crasher_proc; 106 107 printk("loaded crasher module\n"); 108 109 /* build a crasher file that can be set */ 110 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) 111 if ((crasher_proc = create_proc_entry(CRASH, 0, NULL)) == NULL) { 112 return -ENOMEM; 113 } 114 crasher_proc->owner = THIS_MODULE 115 crasher_proc->read_proc = crasher_read; 116 crasher_proc->write_proc = crasher_write; 117 #else 118 crasher_proc = proc_create_data(CRASH, 0, NULL, 119 &crasher_proc_fops, NULL); 120 if (!crasher_proc) 121 return -ENOMEM; 122 #endif 123 return 0; 124 } 125 126 void crasher_exit(void) 127 { 128 remove_proc_entry(CRASH, NULL); 129 printk("removed crasher module\n"); 130 } 131