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 be662a18b7763496a052d489206af9ca2c2e1ac2 452 lines 11 kB view raw
1/* -*- linux-c -*- 2 * 3 * $Id: sysrq.c,v 1.15 1998/08/23 14:56:41 mj 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/kernel.h> 30#include <linux/module.h> 31#include <linux/suspend.h> 32#include <linux/writeback.h> 33#include <linux/buffer_head.h> /* for fsync_bdev() */ 34#include <linux/swap.h> 35#include <linux/spinlock.h> 36#include <linux/vt_kern.h> 37#include <linux/workqueue.h> 38#include <linux/kexec.h> 39 40#include <asm/ptrace.h> 41 42/* Whether we react on sysrq keys or just ignore them */ 43int sysrq_enabled = 1; 44 45/* Loglevel sysrq handler */ 46static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs, 47 struct tty_struct *tty) 48{ 49 int i; 50 i = key - '0'; 51 console_loglevel = 7; 52 printk("Loglevel set to %d\n", i); 53 console_loglevel = i; 54} 55static struct sysrq_key_op sysrq_loglevel_op = { 56 .handler = sysrq_handle_loglevel, 57 .help_msg = "loglevel0-8", 58 .action_msg = "Changing Loglevel", 59 .enable_mask = SYSRQ_ENABLE_LOG, 60}; 61 62 63/* SAK sysrq handler */ 64#ifdef CONFIG_VT 65static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs, 66 struct tty_struct *tty) 67{ 68 if (tty) 69 do_SAK(tty); 70 reset_vc(vc_cons[fg_console].d); 71} 72static struct sysrq_key_op sysrq_SAK_op = { 73 .handler = sysrq_handle_SAK, 74 .help_msg = "saK", 75 .action_msg = "SAK", 76 .enable_mask = SYSRQ_ENABLE_KEYBOARD, 77}; 78#endif 79 80#ifdef CONFIG_VT 81/* unraw sysrq handler */ 82static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs, 83 struct tty_struct *tty) 84{ 85 struct kbd_struct *kbd = &kbd_table[fg_console]; 86 87 if (kbd) 88 kbd->kbdmode = VC_XLATE; 89} 90static struct sysrq_key_op sysrq_unraw_op = { 91 .handler = sysrq_handle_unraw, 92 .help_msg = "unRaw", 93 .action_msg = "Keyboard mode set to XLATE", 94 .enable_mask = SYSRQ_ENABLE_KEYBOARD, 95}; 96#endif /* CONFIG_VT */ 97 98#ifdef CONFIG_KEXEC 99/* crashdump sysrq handler */ 100static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs, 101 struct tty_struct *tty) 102{ 103 crash_kexec(pt_regs); 104} 105static struct sysrq_key_op sysrq_crashdump_op = { 106 .handler = sysrq_handle_crashdump, 107 .help_msg = "Crashdump", 108 .action_msg = "Trigger a crashdump", 109 .enable_mask = SYSRQ_ENABLE_DUMP, 110}; 111#endif 112 113/* reboot sysrq handler */ 114static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs, 115 struct tty_struct *tty) 116{ 117 local_irq_enable(); 118 emergency_restart(); 119} 120 121static struct sysrq_key_op sysrq_reboot_op = { 122 .handler = sysrq_handle_reboot, 123 .help_msg = "reBoot", 124 .action_msg = "Resetting", 125 .enable_mask = SYSRQ_ENABLE_BOOT, 126}; 127 128static void sysrq_handle_sync(int key, struct pt_regs *pt_regs, 129 struct tty_struct *tty) 130{ 131 emergency_sync(); 132} 133 134static struct sysrq_key_op sysrq_sync_op = { 135 .handler = sysrq_handle_sync, 136 .help_msg = "Sync", 137 .action_msg = "Emergency Sync", 138 .enable_mask = SYSRQ_ENABLE_SYNC, 139}; 140 141static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs, 142 struct tty_struct *tty) 143{ 144 emergency_remount(); 145} 146 147static struct sysrq_key_op sysrq_mountro_op = { 148 .handler = sysrq_handle_mountro, 149 .help_msg = "Unmount", 150 .action_msg = "Emergency Remount R/O", 151 .enable_mask = SYSRQ_ENABLE_REMOUNT, 152}; 153 154/* END SYNC SYSRQ HANDLERS BLOCK */ 155 156 157/* SHOW SYSRQ HANDLERS BLOCK */ 158 159static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs, 160 struct tty_struct *tty) 161{ 162 if (pt_regs) 163 show_regs(pt_regs); 164} 165static struct sysrq_key_op sysrq_showregs_op = { 166 .handler = sysrq_handle_showregs, 167 .help_msg = "showPc", 168 .action_msg = "Show Regs", 169 .enable_mask = SYSRQ_ENABLE_DUMP, 170}; 171 172 173static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs, 174 struct tty_struct *tty) 175{ 176 show_state(); 177} 178static struct sysrq_key_op sysrq_showstate_op = { 179 .handler = sysrq_handle_showstate, 180 .help_msg = "showTasks", 181 .action_msg = "Show State", 182 .enable_mask = SYSRQ_ENABLE_DUMP, 183}; 184 185 186static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs, 187 struct tty_struct *tty) 188{ 189 show_mem(); 190} 191static struct sysrq_key_op sysrq_showmem_op = { 192 .handler = sysrq_handle_showmem, 193 .help_msg = "showMem", 194 .action_msg = "Show Memory", 195 .enable_mask = SYSRQ_ENABLE_DUMP, 196}; 197 198/* SHOW SYSRQ HANDLERS BLOCK */ 199 200 201/* SIGNAL SYSRQ HANDLERS BLOCK */ 202 203/* signal sysrq helper function 204 * Sends a signal to all user processes */ 205static void send_sig_all(int sig) 206{ 207 struct task_struct *p; 208 209 for_each_process(p) { 210 if (p->mm && p->pid != 1) 211 /* Not swapper, init nor kernel thread */ 212 force_sig(sig, p); 213 } 214} 215 216static void sysrq_handle_term(int key, struct pt_regs *pt_regs, 217 struct tty_struct *tty) 218{ 219 send_sig_all(SIGTERM); 220 console_loglevel = 8; 221} 222static struct sysrq_key_op sysrq_term_op = { 223 .handler = sysrq_handle_term, 224 .help_msg = "tErm", 225 .action_msg = "Terminate All Tasks", 226 .enable_mask = SYSRQ_ENABLE_SIGNAL, 227}; 228 229static void moom_callback(void *ignored) 230{ 231 out_of_memory(GFP_KERNEL, 0); 232} 233 234static DECLARE_WORK(moom_work, moom_callback, NULL); 235 236static void sysrq_handle_moom(int key, struct pt_regs *pt_regs, 237 struct tty_struct *tty) 238{ 239 schedule_work(&moom_work); 240} 241static struct sysrq_key_op sysrq_moom_op = { 242 .handler = sysrq_handle_moom, 243 .help_msg = "Full", 244 .action_msg = "Manual OOM execution", 245}; 246 247static void sysrq_handle_kill(int key, struct pt_regs *pt_regs, 248 struct tty_struct *tty) 249{ 250 send_sig_all(SIGKILL); 251 console_loglevel = 8; 252} 253static struct sysrq_key_op sysrq_kill_op = { 254 .handler = sysrq_handle_kill, 255 .help_msg = "kIll", 256 .action_msg = "Kill All Tasks", 257 .enable_mask = SYSRQ_ENABLE_SIGNAL, 258}; 259 260/* END SIGNAL SYSRQ HANDLERS BLOCK */ 261 262static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs, 263 struct tty_struct *tty) 264{ 265 normalize_rt_tasks(); 266} 267static struct sysrq_key_op sysrq_unrt_op = { 268 .handler = sysrq_handle_unrt, 269 .help_msg = "Nice", 270 .action_msg = "Nice All RT Tasks", 271 .enable_mask = SYSRQ_ENABLE_RTNICE, 272}; 273 274/* Key Operations table and lock */ 275static DEFINE_SPINLOCK(sysrq_key_table_lock); 276#define SYSRQ_KEY_TABLE_LENGTH 36 277static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = { 278/* 0 */ &sysrq_loglevel_op, 279/* 1 */ &sysrq_loglevel_op, 280/* 2 */ &sysrq_loglevel_op, 281/* 3 */ &sysrq_loglevel_op, 282/* 4 */ &sysrq_loglevel_op, 283/* 5 */ &sysrq_loglevel_op, 284/* 6 */ &sysrq_loglevel_op, 285/* 7 */ &sysrq_loglevel_op, 286/* 8 */ &sysrq_loglevel_op, 287/* 9 */ &sysrq_loglevel_op, 288/* a */ NULL, /* Don't use for system provided sysrqs, 289 it is handled specially on the sparc 290 and will never arrive */ 291/* b */ &sysrq_reboot_op, 292#ifdef CONFIG_KEXEC 293/* c */ &sysrq_crashdump_op, 294#else 295/* c */ NULL, 296#endif 297/* d */ NULL, 298/* e */ &sysrq_term_op, 299/* f */ &sysrq_moom_op, 300/* g */ NULL, 301/* h */ NULL, 302/* i */ &sysrq_kill_op, 303/* j */ NULL, 304#ifdef CONFIG_VT 305/* k */ &sysrq_SAK_op, 306#else 307/* k */ NULL, 308#endif 309/* l */ NULL, 310/* m */ &sysrq_showmem_op, 311/* n */ &sysrq_unrt_op, 312/* o */ NULL, /* This will often be registered 313 as 'Off' at init time */ 314/* p */ &sysrq_showregs_op, 315/* q */ NULL, 316#ifdef CONFIG_VT 317/* r */ &sysrq_unraw_op, 318#else 319/* r */ NULL, 320#endif 321/* s */ &sysrq_sync_op, 322/* t */ &sysrq_showstate_op, 323/* u */ &sysrq_mountro_op, 324/* v */ NULL, /* May be assigned at init time by SMP VOYAGER */ 325/* w */ NULL, 326/* x */ NULL, 327/* y */ NULL, 328/* z */ NULL 329}; 330 331/* key2index calculation, -1 on invalid index */ 332static int sysrq_key_table_key2index(int key) { 333 int retval; 334 if ((key >= '0') && (key <= '9')) { 335 retval = key - '0'; 336 } else if ((key >= 'a') && (key <= 'z')) { 337 retval = key + 10 - 'a'; 338 } else { 339 retval = -1; 340 } 341 return retval; 342} 343 344/* 345 * get and put functions for the table, exposed to modules. 346 */ 347 348struct sysrq_key_op *__sysrq_get_key_op (int key) { 349 struct sysrq_key_op *op_p; 350 int i; 351 352 i = sysrq_key_table_key2index(key); 353 op_p = (i == -1) ? NULL : sysrq_key_table[i]; 354 return op_p; 355} 356 357void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) { 358 int i; 359 360 i = sysrq_key_table_key2index(key); 361 if (i != -1) 362 sysrq_key_table[i] = op_p; 363} 364 365/* 366 * This is the non-locking version of handle_sysrq 367 * It must/can only be called by sysrq key handlers, 368 * as they are inside of the lock 369 */ 370 371void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, int check_mask) 372{ 373 struct sysrq_key_op *op_p; 374 int orig_log_level; 375 int i, j; 376 unsigned long flags; 377 378 spin_lock_irqsave(&sysrq_key_table_lock, flags); 379 orig_log_level = console_loglevel; 380 console_loglevel = 7; 381 printk(KERN_INFO "SysRq : "); 382 383 op_p = __sysrq_get_key_op(key); 384 if (op_p) { 385 /* Should we check for enabled operations (/proc/sysrq-trigger should not) 386 * and is the invoked operation enabled? */ 387 if (!check_mask || sysrq_enabled == 1 || 388 (sysrq_enabled & op_p->enable_mask)) { 389 printk ("%s\n", op_p->action_msg); 390 console_loglevel = orig_log_level; 391 op_p->handler(key, pt_regs, tty); 392 } 393 else 394 printk("This sysrq operation is disabled.\n"); 395 } else { 396 printk("HELP : "); 397 /* Only print the help msg once per handler */ 398 for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++) 399 if (sysrq_key_table[i]) { 400 for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++); 401 if (j == i) 402 printk ("%s ", sysrq_key_table[i]->help_msg); 403 } 404 printk ("\n"); 405 console_loglevel = orig_log_level; 406 } 407 spin_unlock_irqrestore(&sysrq_key_table_lock, flags); 408} 409 410/* 411 * This function is called by the keyboard handler when SysRq is pressed 412 * and any other keycode arrives. 413 */ 414 415void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) 416{ 417 if (!sysrq_enabled) 418 return; 419 __handle_sysrq(key, pt_regs, tty, 1); 420} 421 422int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, 423 struct sysrq_key_op *remove_op_p) { 424 425 int retval; 426 unsigned long flags; 427 428 spin_lock_irqsave(&sysrq_key_table_lock, flags); 429 if (__sysrq_get_key_op(key) == remove_op_p) { 430 __sysrq_put_key_op(key, insert_op_p); 431 retval = 0; 432 } else { 433 retval = -1; 434 } 435 spin_unlock_irqrestore(&sysrq_key_table_lock, flags); 436 437 return retval; 438} 439 440int register_sysrq_key(int key, struct sysrq_key_op *op_p) 441{ 442 return __sysrq_swap_key_ops(key, op_p, NULL); 443} 444 445int unregister_sysrq_key(int key, struct sysrq_key_op *op_p) 446{ 447 return __sysrq_swap_key_ops(key, NULL, op_p); 448} 449 450EXPORT_SYMBOL(handle_sysrq); 451EXPORT_SYMBOL(register_sysrq_key); 452EXPORT_SYMBOL(unregister_sysrq_key);