Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.25-rc3 345 lines 8.0 kB view raw
1/* 2 * Kprobe module for testing crash dumps 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 (C) IBM Corporation, 2006 19 * 20 * Author: Ankita Garg <ankita@in.ibm.com> 21 * 22 * This module induces system failures at predefined crashpoints to 23 * evaluate the reliability of crash dumps obtained using different dumping 24 * solutions. 25 * 26 * It is adapted from the Linux Kernel Dump Test Tool by 27 * Fernando Luis Vazquez Cao <http://lkdtt.sourceforge.net> 28 * 29 * Usage : insmod lkdtm.ko [recur_count={>0}] cpoint_name=<> cpoint_type=<> 30 * [cpoint_count={>0}] 31 * 32 * recur_count : Recursion level for the stack overflow test. Default is 10. 33 * 34 * cpoint_name : Crash point where the kernel is to be crashed. It can be 35 * one of INT_HARDWARE_ENTRY, INT_HW_IRQ_EN, INT_TASKLET_ENTRY, 36 * FS_DEVRW, MEM_SWAPOUT, TIMERADD, SCSI_DISPATCH_CMD, 37 * IDE_CORE_CP 38 * 39 * cpoint_type : Indicates the action to be taken on hitting the crash point. 40 * It can be one of PANIC, BUG, EXCEPTION, LOOP, OVERFLOW 41 * 42 * cpoint_count : Indicates the number of times the crash point is to be hit 43 * to trigger an action. The default is 10. 44 */ 45 46#include <linux/kernel.h> 47#include <linux/fs.h> 48#include <linux/module.h> 49#include <linux/buffer_head.h> 50#include <linux/kprobes.h> 51#include <linux/list.h> 52#include <linux/init.h> 53#include <linux/interrupt.h> 54#include <linux/hrtimer.h> 55#include <scsi/scsi_cmnd.h> 56 57#ifdef CONFIG_IDE 58#include <linux/ide.h> 59#endif 60 61#define NUM_CPOINTS 8 62#define NUM_CPOINT_TYPES 5 63#define DEFAULT_COUNT 10 64#define REC_NUM_DEFAULT 10 65 66enum cname { 67 INVALID, 68 INT_HARDWARE_ENTRY, 69 INT_HW_IRQ_EN, 70 INT_TASKLET_ENTRY, 71 FS_DEVRW, 72 MEM_SWAPOUT, 73 TIMERADD, 74 SCSI_DISPATCH_CMD, 75 IDE_CORE_CP 76}; 77 78enum ctype { 79 NONE, 80 PANIC, 81 BUG, 82 EXCEPTION, 83 LOOP, 84 OVERFLOW 85}; 86 87static char* cp_name[] = { 88 "INT_HARDWARE_ENTRY", 89 "INT_HW_IRQ_EN", 90 "INT_TASKLET_ENTRY", 91 "FS_DEVRW", 92 "MEM_SWAPOUT", 93 "TIMERADD", 94 "SCSI_DISPATCH_CMD", 95 "IDE_CORE_CP" 96}; 97 98static char* cp_type[] = { 99 "PANIC", 100 "BUG", 101 "EXCEPTION", 102 "LOOP", 103 "OVERFLOW" 104}; 105 106static struct jprobe lkdtm; 107 108static int lkdtm_parse_commandline(void); 109static void lkdtm_handler(void); 110 111static char* cpoint_name; 112static char* cpoint_type; 113static int cpoint_count = DEFAULT_COUNT; 114static int recur_count = REC_NUM_DEFAULT; 115 116static enum cname cpoint = INVALID; 117static enum ctype cptype = NONE; 118static int count = DEFAULT_COUNT; 119 120module_param(recur_count, int, 0644); 121MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ 122 "default is 10"); 123module_param(cpoint_name, charp, 0644); 124MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed"); 125module_param(cpoint_type, charp, 0644); 126MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\ 127 "hitting the crash point"); 128module_param(cpoint_count, int, 0644); 129MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\ 130 "crash point is to be hit to trigger action"); 131 132static unsigned int jp_do_irq(unsigned int irq) 133{ 134 lkdtm_handler(); 135 jprobe_return(); 136 return 0; 137} 138 139static irqreturn_t jp_handle_irq_event(unsigned int irq, 140 struct irqaction *action) 141{ 142 lkdtm_handler(); 143 jprobe_return(); 144 return 0; 145} 146 147static void jp_tasklet_action(struct softirq_action *a) 148{ 149 lkdtm_handler(); 150 jprobe_return(); 151} 152 153static void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) 154{ 155 lkdtm_handler(); 156 jprobe_return(); 157} 158 159struct scan_control; 160 161static unsigned long jp_shrink_inactive_list(unsigned long max_scan, 162 struct zone *zone, 163 struct scan_control *sc) 164{ 165 lkdtm_handler(); 166 jprobe_return(); 167 return 0; 168} 169 170static int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim, 171 const enum hrtimer_mode mode) 172{ 173 lkdtm_handler(); 174 jprobe_return(); 175 return 0; 176} 177 178static int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd) 179{ 180 lkdtm_handler(); 181 jprobe_return(); 182 return 0; 183} 184 185#ifdef CONFIG_IDE 186int jp_generic_ide_ioctl(ide_drive_t *drive, struct file *file, 187 struct block_device *bdev, unsigned int cmd, 188 unsigned long arg) 189{ 190 lkdtm_handler(); 191 jprobe_return(); 192 return 0; 193} 194#endif 195 196static int lkdtm_parse_commandline(void) 197{ 198 int i; 199 200 if (cpoint_name == INVALID || cpoint_type == NONE || 201 cpoint_count < 1 || recur_count < 1) 202 return -EINVAL; 203 204 for (i = 0; i < NUM_CPOINTS; ++i) { 205 if (!strcmp(cpoint_name, cp_name[i])) { 206 cpoint = i + 1; 207 break; 208 } 209 } 210 211 for (i = 0; i < NUM_CPOINT_TYPES; ++i) { 212 if (!strcmp(cpoint_type, cp_type[i])) { 213 cptype = i + 1; 214 break; 215 } 216 } 217 218 if (cpoint == INVALID || cptype == NONE) 219 return -EINVAL; 220 221 count = cpoint_count; 222 223 return 0; 224} 225 226static int recursive_loop(int a) 227{ 228 char buf[1024]; 229 230 memset(buf,0xFF,1024); 231 recur_count--; 232 if (!recur_count) 233 return 0; 234 else 235 return recursive_loop(a); 236} 237 238void lkdtm_handler(void) 239{ 240 printk(KERN_INFO "lkdtm : Crash point %s of type %s hit\n", 241 cpoint_name, cpoint_type); 242 --count; 243 244 if (count == 0) { 245 switch (cptype) { 246 case NONE: 247 break; 248 case PANIC: 249 printk(KERN_INFO "lkdtm : PANIC\n"); 250 panic("dumptest"); 251 break; 252 case BUG: 253 printk(KERN_INFO "lkdtm : BUG\n"); 254 BUG(); 255 break; 256 case EXCEPTION: 257 printk(KERN_INFO "lkdtm : EXCEPTION\n"); 258 *((int *) 0) = 0; 259 break; 260 case LOOP: 261 printk(KERN_INFO "lkdtm : LOOP\n"); 262 for (;;); 263 break; 264 case OVERFLOW: 265 printk(KERN_INFO "lkdtm : OVERFLOW\n"); 266 (void) recursive_loop(0); 267 break; 268 default: 269 break; 270 } 271 count = cpoint_count; 272 } 273} 274 275static int __init lkdtm_module_init(void) 276{ 277 int ret; 278 279 if (lkdtm_parse_commandline() == -EINVAL) { 280 printk(KERN_INFO "lkdtm : Invalid command\n"); 281 return -EINVAL; 282 } 283 284 switch (cpoint) { 285 case INT_HARDWARE_ENTRY: 286 lkdtm.kp.symbol_name = "__do_IRQ"; 287 lkdtm.entry = (kprobe_opcode_t*) jp_do_irq; 288 break; 289 case INT_HW_IRQ_EN: 290 lkdtm.kp.symbol_name = "handle_IRQ_event"; 291 lkdtm.entry = (kprobe_opcode_t*) jp_handle_irq_event; 292 break; 293 case INT_TASKLET_ENTRY: 294 lkdtm.kp.symbol_name = "tasklet_action"; 295 lkdtm.entry = (kprobe_opcode_t*) jp_tasklet_action; 296 break; 297 case FS_DEVRW: 298 lkdtm.kp.symbol_name = "ll_rw_block"; 299 lkdtm.entry = (kprobe_opcode_t*) jp_ll_rw_block; 300 break; 301 case MEM_SWAPOUT: 302 lkdtm.kp.symbol_name = "shrink_inactive_list"; 303 lkdtm.entry = (kprobe_opcode_t*) jp_shrink_inactive_list; 304 break; 305 case TIMERADD: 306 lkdtm.kp.symbol_name = "hrtimer_start"; 307 lkdtm.entry = (kprobe_opcode_t*) jp_hrtimer_start; 308 break; 309 case SCSI_DISPATCH_CMD: 310 lkdtm.kp.symbol_name = "scsi_dispatch_cmd"; 311 lkdtm.entry = (kprobe_opcode_t*) jp_scsi_dispatch_cmd; 312 break; 313 case IDE_CORE_CP: 314#ifdef CONFIG_IDE 315 lkdtm.kp.symbol_name = "generic_ide_ioctl"; 316 lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl; 317#else 318 printk(KERN_INFO "lkdtm : Crash point not available\n"); 319#endif 320 break; 321 default: 322 printk(KERN_INFO "lkdtm : Invalid Crash Point\n"); 323 break; 324 } 325 326 if ((ret = register_jprobe(&lkdtm)) < 0) { 327 printk(KERN_INFO "lkdtm : Couldn't register jprobe\n"); 328 return ret; 329 } 330 331 printk(KERN_INFO "lkdtm : Crash point %s of type %s registered\n", 332 cpoint_name, cpoint_type); 333 return 0; 334} 335 336static void __exit lkdtm_module_exit(void) 337{ 338 unregister_jprobe(&lkdtm); 339 printk(KERN_INFO "lkdtm : Crash point unregistered\n"); 340} 341 342module_init(lkdtm_module_init); 343module_exit(lkdtm_module_exit); 344 345MODULE_LICENSE("GPL");