1/* -*- linux-c -*- 2 * 3 * $Id: sysrq.c,v 1.1.1.1 2008/10/15 03:26:28 james26_jang Exp $ 4 * 5 * Linux Magic System Request Key Hacks 6 * 7 * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> 8 * based on ideas by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz> 9 * 10 * (c) 2000 Crutcher Dunnavant <crutcher+kernel@datastacks.com> 11 * overhauled to use key registration 12 * based upon discusions in irc://irc.openprojects.net/#kernelnewbies 13 */ 14 15#include <linux/config.h> 16#include <linux/sched.h> 17#include <linux/interrupt.h> 18#include <linux/mm.h> 19#include <linux/fs.h> 20#include <linux/tty.h> 21#include <linux/mount.h> 22#include <linux/kdev_t.h> 23#include <linux/major.h> 24#include <linux/reboot.h> 25#include <linux/sysrq.h> 26#include <linux/kbd_kern.h> 27#include <linux/quotaops.h> 28#include <linux/smp_lock.h> 29#include <linux/module.h> 30 31#include <linux/spinlock.h> 32 33#include <asm/ptrace.h> 34 35extern void reset_vc(unsigned int); 36extern struct list_head super_blocks; 37 38/* Whether we react on sysrq keys or just ignore them */ 39int sysrq_enabled = 1; 40 41/* Machine specific power off function */ 42void (*sysrq_power_off)(void); 43 44/* Loglevel sysrq handler */ 45static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs, 46 struct kbd_struct *kbd, struct tty_struct *tty) { 47 int i; 48 i = key - '0'; 49 console_loglevel = 7; 50 printk("Loglevel set to %d\n", i); 51 console_loglevel = i; 52} 53static struct sysrq_key_op sysrq_loglevel_op = { 54 handler: sysrq_handle_loglevel, 55 help_msg: "loglevel0-8", 56 action_msg: "Changing Loglevel", 57}; 58 59 60/* SAK sysrq handler */ 61#ifdef CONFIG_VT 62static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs, 63 struct kbd_struct *kbd, struct tty_struct *tty) { 64 if (tty) 65 do_SAK(tty); 66 reset_vc(fg_console); 67} 68static struct sysrq_key_op sysrq_SAK_op = { 69 handler: sysrq_handle_SAK, 70 help_msg: "saK", 71 action_msg: "SAK", 72}; 73#endif 74 75 76/* unraw sysrq handler */ 77static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs, 78 struct kbd_struct *kbd, struct tty_struct *tty) { 79 if (kbd) 80 kbd->kbdmode = VC_XLATE; 81} 82static struct sysrq_key_op sysrq_unraw_op = { 83 handler: sysrq_handle_unraw, 84 help_msg: "unRaw", 85 action_msg: "Keyboard mode set to XLATE", 86}; 87 88 89/* reboot sysrq handler */ 90static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs, 91 struct kbd_struct *kbd, struct tty_struct *tty) { 92 machine_restart(NULL); 93} 94static struct sysrq_key_op sysrq_reboot_op = { 95 handler: sysrq_handle_reboot, 96 help_msg: "reBoot", 97 action_msg: "Resetting", 98}; 99 100 101 102/* SYNC SYSRQ HANDLERS BLOCK */ 103 104/* do_emergency_sync helper function */ 105/* Guesses if the device is a local hard drive */ 106static int is_local_disk(kdev_t dev) { 107 unsigned int major; 108 major = MAJOR(dev); 109 110 switch (major) { 111 case IDE0_MAJOR: 112 case IDE1_MAJOR: 113 case IDE2_MAJOR: 114 case IDE3_MAJOR: 115 case IDE4_MAJOR: 116 case IDE5_MAJOR: 117 case IDE6_MAJOR: 118 case IDE7_MAJOR: 119 case IDE8_MAJOR: 120 case IDE9_MAJOR: 121 case SCSI_DISK0_MAJOR: 122 case SCSI_DISK1_MAJOR: 123 case SCSI_DISK2_MAJOR: 124 case SCSI_DISK3_MAJOR: 125 case SCSI_DISK4_MAJOR: 126 case SCSI_DISK5_MAJOR: 127 case SCSI_DISK6_MAJOR: 128 case SCSI_DISK7_MAJOR: 129 case XT_DISK_MAJOR: 130 return 1; 131 default: 132 return 0; 133 } 134} 135 136/* do_emergency_sync helper function */ 137static void go_sync(struct super_block *sb, int remount_flag) 138{ 139 int orig_loglevel; 140 orig_loglevel = console_loglevel; 141 console_loglevel = 7; 142 printk(KERN_INFO "%sing device %s ... ", 143 remount_flag ? "Remount" : "Sync", 144 kdevname(sb->s_dev)); 145 146 if (remount_flag) { /* Remount R/O */ 147 int ret, flags; 148 struct list_head *p; 149 150 if (sb->s_flags & MS_RDONLY) { 151 printk("R/O\n"); 152 return; 153 } 154 155 file_list_lock(); 156 for (p = sb->s_files.next; p != &sb->s_files; p = p->next) { 157 struct file *file = list_entry(p, struct file, f_list); 158 if (file->f_dentry && file_count(file) 159 && S_ISREG(file->f_dentry->d_inode->i_mode)) 160 file->f_mode &= ~2; 161 } 162 file_list_unlock(); 163 DQUOT_OFF(sb); 164 fsync_dev(sb->s_dev); 165 flags = MS_RDONLY; 166 if (sb->s_op && sb->s_op->remount_fs) { 167 ret = sb->s_op->remount_fs(sb, &flags, NULL); 168 if (ret) 169 printk("error %d\n", ret); 170 else { 171 sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); 172 printk("OK\n"); 173 } 174 } else 175 printk("nothing to do\n"); 176 } else { /* Sync only */ 177 fsync_dev(sb->s_dev); 178 printk("OK\n"); 179 } 180 console_loglevel = orig_loglevel; 181} 182/* 183 * Emergency Sync or Unmount. We cannot do it directly, so we set a special 184 * flag and wake up the bdflush kernel thread which immediately calls this function. 185 * We process all mounted hard drives first to recover from crashed experimental 186 * block devices and malfunctional network filesystems. 187 */ 188 189volatile int emergency_sync_scheduled; 190 191void do_emergency_sync(void) { 192 struct super_block *sb; 193 int remount_flag; 194 int orig_loglevel; 195 196 lock_kernel(); 197 remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT); 198 emergency_sync_scheduled = 0; 199 200 for (sb = sb_entry(super_blocks.next); 201 sb != sb_entry(&super_blocks); 202 sb = sb_entry(sb->s_list.next)) 203 if (is_local_disk(sb->s_dev)) 204 go_sync(sb, remount_flag); 205 206 for (sb = sb_entry(super_blocks.next); 207 sb != sb_entry(&super_blocks); 208 sb = sb_entry(sb->s_list.next)) 209 if (!is_local_disk(sb->s_dev) && MAJOR(sb->s_dev)) 210 go_sync(sb, remount_flag); 211 212 unlock_kernel(); 213 214 orig_loglevel = console_loglevel; 215 console_loglevel = 7; 216 printk(KERN_INFO "Done.\n"); 217 console_loglevel = orig_loglevel; 218} 219 220static void sysrq_handle_sync(int key, struct pt_regs *pt_regs, 221 struct kbd_struct *kbd, struct tty_struct *tty) { 222 emergency_sync_scheduled = EMERG_SYNC; 223 wakeup_bdflush(); 224} 225static struct sysrq_key_op sysrq_sync_op = { 226 handler: sysrq_handle_sync, 227 help_msg: "Sync", 228 action_msg: "Emergency Sync", 229}; 230 231static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs, 232 struct kbd_struct *kbd, struct tty_struct *tty) { 233 emergency_sync_scheduled = EMERG_REMOUNT; 234 wakeup_bdflush(); 235} 236static struct sysrq_key_op sysrq_mountro_op = { 237 handler: sysrq_handle_mountro, 238 help_msg: "Unmount", 239 action_msg: "Emergency Remount R/O", 240}; 241 242/* END SYNC SYSRQ HANDLERS BLOCK */ 243 244 245/* SHOW SYSRQ HANDLERS BLOCK */ 246 247static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs, 248 struct kbd_struct *kbd, struct tty_struct *tty) { 249 if (pt_regs) 250 show_regs(pt_regs); 251} 252static struct sysrq_key_op sysrq_showregs_op = { 253 handler: sysrq_handle_showregs, 254 help_msg: "showPc", 255 action_msg: "Show Regs", 256}; 257 258 259static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs, 260 struct kbd_struct *kbd, struct tty_struct *tty) { 261 show_state(); 262} 263static struct sysrq_key_op sysrq_showstate_op = { 264 handler: sysrq_handle_showstate, 265 help_msg: "showTasks", 266 action_msg: "Show State", 267}; 268 269 270static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs, 271 struct kbd_struct *kbd, struct tty_struct *tty) { 272 show_mem(); 273} 274static struct sysrq_key_op sysrq_showmem_op = { 275 handler: sysrq_handle_showmem, 276 help_msg: "showMem", 277 action_msg: "Show Memory", 278}; 279 280/* SHOW SYSRQ HANDLERS BLOCK */ 281 282 283/* SIGNAL SYSRQ HANDLERS BLOCK */ 284 285/* signal sysrq helper function 286 * Sends a signal to all user processes */ 287static void send_sig_all(int sig) 288{ 289 struct task_struct *p; 290 291 for_each_task(p) { 292 if (p->mm && p->pid != 1) 293 /* Not swapper, init nor kernel thread */ 294 force_sig(sig, p); 295 } 296} 297 298static void sysrq_handle_term(int key, struct pt_regs *pt_regs, 299 struct kbd_struct *kbd, struct tty_struct *tty) { 300 send_sig_all(SIGTERM); 301 console_loglevel = 8; 302} 303static struct sysrq_key_op sysrq_term_op = { 304 handler: sysrq_handle_term, 305 help_msg: "tErm", 306 action_msg: "Terminate All Tasks", 307}; 308 309static void sysrq_handle_kill(int key, struct pt_regs *pt_regs, 310 struct kbd_struct *kbd, struct tty_struct *tty) { 311 send_sig_all(SIGKILL); 312 console_loglevel = 8; 313} 314static struct sysrq_key_op sysrq_kill_op = { 315 handler: sysrq_handle_kill, 316 help_msg: "kIll", 317 action_msg: "Kill All Tasks", 318}; 319 320/* END SIGNAL SYSRQ HANDLERS BLOCK */ 321 322 323/* Key Operations table and lock */ 324static spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED; 325#define SYSRQ_KEY_TABLE_LENGTH 36 326static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = { 327/* 0 */ &sysrq_loglevel_op, 328/* 1 */ &sysrq_loglevel_op, 329/* 2 */ &sysrq_loglevel_op, 330/* 3 */ &sysrq_loglevel_op, 331/* 4 */ &sysrq_loglevel_op, 332/* 5 */ &sysrq_loglevel_op, 333/* 6 */ &sysrq_loglevel_op, 334/* 7 */ &sysrq_loglevel_op, 335/* 8 */ &sysrq_loglevel_op, 336/* 9 */ &sysrq_loglevel_op, 337/* a */ NULL, /* Don't use for system provided sysrqs, 338 it is handled specially on the spark 339 and will never arive */ 340/* b */ &sysrq_reboot_op, 341/* c */ NULL, 342/* d */ NULL, 343/* e */ &sysrq_term_op, 344/* f */ NULL, 345/* g */ NULL, 346/* h */ NULL, 347/* i */ &sysrq_kill_op, 348/* j */ NULL, 349#ifdef CONFIG_VT 350/* k */ &sysrq_SAK_op, 351#else 352/* k */ NULL, 353#endif 354/* l */ NULL, 355/* m */ &sysrq_showmem_op, 356/* n */ NULL, 357/* o */ NULL, /* This will often be registered 358 as 'Off' at init time */ 359/* p */ &sysrq_showregs_op, 360/* q */ NULL, 361/* r */ &sysrq_unraw_op, 362/* s */ &sysrq_sync_op, 363/* t */ &sysrq_showstate_op, 364/* u */ &sysrq_mountro_op, 365/* v */ NULL, 366/* w */ NULL, 367/* x */ NULL, 368/* w */ NULL, 369/* z */ NULL 370}; 371 372/* key2index calculation, -1 on invalid index */ 373static __inline__ int sysrq_key_table_key2index(int key) { 374 int retval; 375 if ((key >= '0') & (key <= '9')) { 376 retval = key - '0'; 377 } else if ((key >= 'a') & (key <= 'z')) { 378 retval = key + 10 - 'a'; 379 } else { 380 retval = -1; 381 } 382 return retval; 383} 384 385/* 386 * table lock and unlocking functions, exposed to modules 387 */ 388 389void __sysrq_lock_table (void) { spin_lock(&sysrq_key_table_lock); } 390 391void __sysrq_unlock_table (void) { spin_unlock(&sysrq_key_table_lock); } 392 393/* 394 * get and put functions for the table, exposed to modules. 395 */ 396 397struct sysrq_key_op *__sysrq_get_key_op (int key) { 398 struct sysrq_key_op *op_p; 399 int i; 400 401 i = sysrq_key_table_key2index(key); 402 op_p = (i == -1) ? NULL : sysrq_key_table[i]; 403 return op_p; 404} 405 406void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) { 407 int i; 408 409 i = sysrq_key_table_key2index(key); 410 if (i != -1) 411 sysrq_key_table[i] = op_p; 412} 413 414/* 415 * This function is called by the keyboard handler when SysRq is pressed 416 * and any other keycode arrives. 417 */ 418 419void handle_sysrq(int key, struct pt_regs *pt_regs, 420 struct kbd_struct *kbd, struct tty_struct *tty) { 421 if (!sysrq_enabled) 422 return; 423 424 __sysrq_lock_table(); 425 __handle_sysrq_nolock(key, pt_regs, kbd, tty); 426 __sysrq_unlock_table(); 427} 428 429/* 430 * This is the non-locking version of handle_sysrq 431 * It must/can only be called by sysrq key handlers, 432 * as they are inside of the lock 433 */ 434 435void __handle_sysrq_nolock(int key, struct pt_regs *pt_regs, 436 struct kbd_struct *kbd, struct tty_struct *tty) { 437 struct sysrq_key_op *op_p; 438 int orig_log_level; 439 int i, j; 440 441 if (!sysrq_enabled) 442 return; 443 444 orig_log_level = console_loglevel; 445 console_loglevel = 7; 446 printk(KERN_INFO "SysRq : "); 447 448 op_p = __sysrq_get_key_op(key); 449 if (op_p) { 450 printk ("%s\n", op_p->action_msg); 451 console_loglevel = orig_log_level; 452 op_p->handler(key, pt_regs, kbd, tty); 453 } else { 454 printk("HELP : "); 455 /* Only print the help msg once per handler */ 456 for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++) 457 if (sysrq_key_table[i]) { 458 for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++); 459 if (j == i) 460 printk ("%s ", sysrq_key_table[i]->help_msg); 461 } 462 printk ("\n"); 463 console_loglevel = orig_log_level; 464 } 465} 466 467EXPORT_SYMBOL(handle_sysrq); 468EXPORT_SYMBOL(__handle_sysrq_nolock); 469EXPORT_SYMBOL(__sysrq_lock_table); 470EXPORT_SYMBOL(__sysrq_unlock_table); 471EXPORT_SYMBOL(__sysrq_get_key_op); 472EXPORT_SYMBOL(__sysrq_put_key_op); 473