aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/sysrq.c250
1 files changed, 115 insertions, 135 deletions
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index d58f82318853..35082dc12eae 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -42,16 +42,15 @@
42/* Whether we react on sysrq keys or just ignore them */ 42/* Whether we react on sysrq keys or just ignore them */
43int sysrq_enabled = 1; 43int sysrq_enabled = 1;
44 44
45/* Loglevel sysrq handler */
46static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs, 45static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
47 struct tty_struct *tty) 46 struct tty_struct *tty)
48{ 47{
49 int i; 48 int i;
50 i = key - '0'; 49 i = key - '0';
51 console_loglevel = 7; 50 console_loglevel = 7;
52 printk("Loglevel set to %d\n", i); 51 printk("Loglevel set to %d\n", i);
53 console_loglevel = i; 52 console_loglevel = i;
54} 53}
55static struct sysrq_key_op sysrq_loglevel_op = { 54static struct sysrq_key_op sysrq_loglevel_op = {
56 .handler = sysrq_handle_loglevel, 55 .handler = sysrq_handle_loglevel,
57 .help_msg = "loglevel0-8", 56 .help_msg = "loglevel0-8",
@@ -59,11 +58,9 @@ static struct sysrq_key_op sysrq_loglevel_op = {
59 .enable_mask = SYSRQ_ENABLE_LOG, 58 .enable_mask = SYSRQ_ENABLE_LOG,
60}; 59};
61 60
62
63/* SAK sysrq handler */
64#ifdef CONFIG_VT 61#ifdef CONFIG_VT
65static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs, 62static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
66 struct tty_struct *tty) 63 struct tty_struct *tty)
67{ 64{
68 if (tty) 65 if (tty)
69 do_SAK(tty); 66 do_SAK(tty);
@@ -75,12 +72,13 @@ static struct sysrq_key_op sysrq_SAK_op = {
75 .action_msg = "SAK", 72 .action_msg = "SAK",
76 .enable_mask = SYSRQ_ENABLE_KEYBOARD, 73 .enable_mask = SYSRQ_ENABLE_KEYBOARD,
77}; 74};
75#else
76#define sysrq_SAK_op (*(struct sysrq_key_op *)0)
78#endif 77#endif
79 78
80#ifdef CONFIG_VT 79#ifdef CONFIG_VT
81/* unraw sysrq handler */
82static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs, 80static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
83 struct tty_struct *tty) 81 struct tty_struct *tty)
84{ 82{
85 struct kbd_struct *kbd = &kbd_table[fg_console]; 83 struct kbd_struct *kbd = &kbd_table[fg_console];
86 84
@@ -93,10 +91,11 @@ static struct sysrq_key_op sysrq_unraw_op = {
93 .action_msg = "Keyboard mode set to XLATE", 91 .action_msg = "Keyboard mode set to XLATE",
94 .enable_mask = SYSRQ_ENABLE_KEYBOARD, 92 .enable_mask = SYSRQ_ENABLE_KEYBOARD,
95}; 93};
94#else
95#define sysrq_unraw_op (*(struct sysrq_key_op *)0)
96#endif /* CONFIG_VT */ 96#endif /* CONFIG_VT */
97 97
98#ifdef CONFIG_KEXEC 98#ifdef CONFIG_KEXEC
99/* crashdump sysrq handler */
100static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs, 99static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs,
101 struct tty_struct *tty) 100 struct tty_struct *tty)
102{ 101{
@@ -108,16 +107,16 @@ static struct sysrq_key_op sysrq_crashdump_op = {
108 .action_msg = "Trigger a crashdump", 107 .action_msg = "Trigger a crashdump",
109 .enable_mask = SYSRQ_ENABLE_DUMP, 108 .enable_mask = SYSRQ_ENABLE_DUMP,
110}; 109};
110#else
111#define sysrq_crashdump_op (*(struct sysrq_key_op *)0)
111#endif 112#endif
112 113
113/* reboot sysrq handler */
114static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs, 114static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
115 struct tty_struct *tty) 115 struct tty_struct *tty)
116{ 116{
117 local_irq_enable(); 117 local_irq_enable();
118 emergency_restart(); 118 emergency_restart();
119} 119}
120
121static struct sysrq_key_op sysrq_reboot_op = { 120static struct sysrq_key_op sysrq_reboot_op = {
122 .handler = sysrq_handle_reboot, 121 .handler = sysrq_handle_reboot,
123 .help_msg = "reBoot", 122 .help_msg = "reBoot",
@@ -126,11 +125,10 @@ static struct sysrq_key_op sysrq_reboot_op = {
126}; 125};
127 126
128static void sysrq_handle_sync(int key, struct pt_regs *pt_regs, 127static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
129 struct tty_struct *tty) 128 struct tty_struct *tty)
130{ 129{
131 emergency_sync(); 130 emergency_sync();
132} 131}
133
134static struct sysrq_key_op sysrq_sync_op = { 132static struct sysrq_key_op sysrq_sync_op = {
135 .handler = sysrq_handle_sync, 133 .handler = sysrq_handle_sync,
136 .help_msg = "Sync", 134 .help_msg = "Sync",
@@ -139,11 +137,10 @@ static struct sysrq_key_op sysrq_sync_op = {
139}; 137};
140 138
141static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs, 139static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
142 struct tty_struct *tty) 140 struct tty_struct *tty)
143{ 141{
144 emergency_remount(); 142 emergency_remount();
145} 143}
146
147static struct sysrq_key_op sysrq_mountro_op = { 144static struct sysrq_key_op sysrq_mountro_op = {
148 .handler = sysrq_handle_mountro, 145 .handler = sysrq_handle_mountro,
149 .help_msg = "Unmount", 146 .help_msg = "Unmount",
@@ -151,28 +148,23 @@ static struct sysrq_key_op sysrq_mountro_op = {
151 .enable_mask = SYSRQ_ENABLE_REMOUNT, 148 .enable_mask = SYSRQ_ENABLE_REMOUNT,
152}; 149};
153 150
154/* END SYNC SYSRQ HANDLERS BLOCK */
155
156#ifdef CONFIG_DEBUG_MUTEXES 151#ifdef CONFIG_DEBUG_MUTEXES
157 152static void sysrq_handle_showlocks(int key, struct pt_regs *pt_regs,
158static void 153 struct tty_struct *tty)
159sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
160{ 154{
161 mutex_debug_show_all_locks(); 155 mutex_debug_show_all_locks();
162} 156}
163
164static struct sysrq_key_op sysrq_showlocks_op = { 157static struct sysrq_key_op sysrq_showlocks_op = {
165 .handler = sysrq_handle_showlocks, 158 .handler = sysrq_handle_showlocks,
166 .help_msg = "show-all-locks(D)", 159 .help_msg = "show-all-locks(D)",
167 .action_msg = "Show Locks Held", 160 .action_msg = "Show Locks Held",
168}; 161};
169 162#else
163#define sysrq_showlocks_op (*(struct sysrq_key_op *)0)
170#endif 164#endif
171 165
172/* SHOW SYSRQ HANDLERS BLOCK */
173
174static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs, 166static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
175 struct tty_struct *tty) 167 struct tty_struct *tty)
176{ 168{
177 if (pt_regs) 169 if (pt_regs)
178 show_regs(pt_regs); 170 show_regs(pt_regs);
@@ -184,9 +176,8 @@ static struct sysrq_key_op sysrq_showregs_op = {
184 .enable_mask = SYSRQ_ENABLE_DUMP, 176 .enable_mask = SYSRQ_ENABLE_DUMP,
185}; 177};
186 178
187
188static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs, 179static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
189 struct tty_struct *tty) 180 struct tty_struct *tty)
190{ 181{
191 show_state(); 182 show_state();
192} 183}
@@ -197,9 +188,8 @@ static struct sysrq_key_op sysrq_showstate_op = {
197 .enable_mask = SYSRQ_ENABLE_DUMP, 188 .enable_mask = SYSRQ_ENABLE_DUMP,
198}; 189};
199 190
200
201static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs, 191static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
202 struct tty_struct *tty) 192 struct tty_struct *tty)
203{ 193{
204 show_mem(); 194 show_mem();
205} 195}
@@ -210,13 +200,9 @@ static struct sysrq_key_op sysrq_showmem_op = {
210 .enable_mask = SYSRQ_ENABLE_DUMP, 200 .enable_mask = SYSRQ_ENABLE_DUMP,
211}; 201};
212 202
213/* SHOW SYSRQ HANDLERS BLOCK */ 203/*
214 204 * Signal sysrq helper function. Sends a signal to all user processes.
215 205 */
216/* SIGNAL SYSRQ HANDLERS BLOCK */
217
218/* signal sysrq helper function
219 * Sends a signal to all user processes */
220static void send_sig_all(int sig) 206static void send_sig_all(int sig)
221{ 207{
222 struct task_struct *p; 208 struct task_struct *p;
@@ -229,7 +215,7 @@ static void send_sig_all(int sig)
229} 215}
230 216
231static void sysrq_handle_term(int key, struct pt_regs *pt_regs, 217static void sysrq_handle_term(int key, struct pt_regs *pt_regs,
232 struct tty_struct *tty) 218 struct tty_struct *tty)
233{ 219{
234 send_sig_all(SIGTERM); 220 send_sig_all(SIGTERM);
235 console_loglevel = 8; 221 console_loglevel = 8;
@@ -243,7 +229,8 @@ static struct sysrq_key_op sysrq_term_op = {
243 229
244static void moom_callback(void *ignored) 230static void moom_callback(void *ignored)
245{ 231{
246 out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0); 232 out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL],
233 GFP_KERNEL, 0);
247} 234}
248 235
249static DECLARE_WORK(moom_work, moom_callback, NULL); 236static DECLARE_WORK(moom_work, moom_callback, NULL);
@@ -260,7 +247,7 @@ static struct sysrq_key_op sysrq_moom_op = {
260}; 247};
261 248
262static void sysrq_handle_kill(int key, struct pt_regs *pt_regs, 249static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
263 struct tty_struct *tty) 250 struct tty_struct *tty)
264{ 251{
265 send_sig_all(SIGKILL); 252 send_sig_all(SIGKILL);
266 console_loglevel = 8; 253 console_loglevel = 8;
@@ -272,8 +259,6 @@ static struct sysrq_key_op sysrq_kill_op = {
272 .enable_mask = SYSRQ_ENABLE_SIGNAL, 259 .enable_mask = SYSRQ_ENABLE_SIGNAL,
273}; 260};
274 261
275/* END SIGNAL SYSRQ HANDLERS BLOCK */
276
277static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs, 262static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs,
278 struct tty_struct *tty) 263 struct tty_struct *tty)
279{ 264{
@@ -288,110 +273,99 @@ static struct sysrq_key_op sysrq_unrt_op = {
288 273
289/* Key Operations table and lock */ 274/* Key Operations table and lock */
290static DEFINE_SPINLOCK(sysrq_key_table_lock); 275static DEFINE_SPINLOCK(sysrq_key_table_lock);
291#define SYSRQ_KEY_TABLE_LENGTH 36 276
292static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = { 277static struct sysrq_key_op *sysrq_key_table[36] = {
293/* 0 */ &sysrq_loglevel_op, 278 &sysrq_loglevel_op, /* 0 */
294/* 1 */ &sysrq_loglevel_op, 279 &sysrq_loglevel_op, /* 1 */
295/* 2 */ &sysrq_loglevel_op, 280 &sysrq_loglevel_op, /* 2 */
296/* 3 */ &sysrq_loglevel_op, 281 &sysrq_loglevel_op, /* 3 */
297/* 4 */ &sysrq_loglevel_op, 282 &sysrq_loglevel_op, /* 4 */
298/* 5 */ &sysrq_loglevel_op, 283 &sysrq_loglevel_op, /* 5 */
299/* 6 */ &sysrq_loglevel_op, 284 &sysrq_loglevel_op, /* 6 */
300/* 7 */ &sysrq_loglevel_op, 285 &sysrq_loglevel_op, /* 7 */
301/* 8 */ &sysrq_loglevel_op, 286 &sysrq_loglevel_op, /* 8 */
302/* 9 */ &sysrq_loglevel_op, 287 &sysrq_loglevel_op, /* 9 */
303/* a */ NULL, /* Don't use for system provided sysrqs, 288
304 it is handled specially on the sparc 289 /*
305 and will never arrive */ 290 * Don't use for system provided sysrqs, it is handled specially on
306/* b */ &sysrq_reboot_op, 291 * sparc and will never arrive
307#ifdef CONFIG_KEXEC 292 */
308/* c */ &sysrq_crashdump_op, 293 NULL, /* a */
309#else 294 &sysrq_reboot_op, /* b */
310/* c */ NULL, 295 &sysrq_crashdump_op, /* c */
311#endif 296 &sysrq_showlocks_op, /* d */
312#ifdef CONFIG_DEBUG_MUTEXES 297 &sysrq_term_op, /* e */
313/* d */ &sysrq_showlocks_op, 298 &sysrq_moom_op, /* f */
314#else 299 NULL, /* g */
315/* d */ NULL, 300 NULL, /* h */
316#endif 301 &sysrq_kill_op, /* i */
317/* e */ &sysrq_term_op, 302 NULL, /* j */
318/* f */ &sysrq_moom_op, 303 &sysrq_SAK_op, /* k */
319/* g */ NULL, 304 NULL, /* l */
320/* h */ NULL, 305 &sysrq_showmem_op, /* m */
321/* i */ &sysrq_kill_op, 306 &sysrq_unrt_op, /* n */
322/* j */ NULL, 307 /* This will often be registered as 'Off' at init time */
323#ifdef CONFIG_VT 308 NULL, /* o */
324/* k */ &sysrq_SAK_op, 309 &sysrq_showregs_op, /* p */
325#else 310 NULL, /* q */
326/* k */ NULL, 311 &sysrq_unraw_op, /* r */
327#endif 312 &sysrq_sync_op, /* s */
328/* l */ NULL, 313 &sysrq_showstate_op, /* t */
329/* m */ &sysrq_showmem_op, 314 &sysrq_mountro_op, /* u */
330/* n */ &sysrq_unrt_op, 315 /* May be assigned at init time by SMP VOYAGER */
331/* o */ NULL, /* This will often be registered 316 NULL, /* v */
332 as 'Off' at init time */ 317 NULL, /* w */
333/* p */ &sysrq_showregs_op, 318 NULL, /* x */
334/* q */ NULL, 319 NULL, /* y */
335#ifdef CONFIG_VT 320 NULL /* z */
336/* r */ &sysrq_unraw_op,
337#else
338/* r */ NULL,
339#endif
340/* s */ &sysrq_sync_op,
341/* t */ &sysrq_showstate_op,
342/* u */ &sysrq_mountro_op,
343/* v */ NULL, /* May be assigned at init time by SMP VOYAGER */
344/* w */ NULL,
345/* x */ NULL,
346/* y */ NULL,
347/* z */ NULL
348}; 321};
349 322
350/* key2index calculation, -1 on invalid index */ 323/* key2index calculation, -1 on invalid index */
351static int sysrq_key_table_key2index(int key) { 324static int sysrq_key_table_key2index(int key)
325{
352 int retval; 326 int retval;
353 if ((key >= '0') && (key <= '9')) { 327
328 if ((key >= '0') && (key <= '9'))
354 retval = key - '0'; 329 retval = key - '0';
355 } else if ((key >= 'a') && (key <= 'z')) { 330 else if ((key >= 'a') && (key <= 'z'))
356 retval = key + 10 - 'a'; 331 retval = key + 10 - 'a';
357 } else { 332 else
358 retval = -1; 333 retval = -1;
359 }
360 return retval; 334 return retval;
361} 335}
362 336
363/* 337/*
364 * get and put functions for the table, exposed to modules. 338 * get and put functions for the table, exposed to modules.
365 */ 339 */
366 340struct sysrq_key_op *__sysrq_get_key_op(int key)
367struct sysrq_key_op *__sysrq_get_key_op (int key) { 341{
368 struct sysrq_key_op *op_p; 342 struct sysrq_key_op *op_p = NULL;
369 int i; 343 int i;
370 344
371 i = sysrq_key_table_key2index(key); 345 i = sysrq_key_table_key2index(key);
372 op_p = (i == -1) ? NULL : sysrq_key_table[i]; 346 if (i != -1)
347 op_p = sysrq_key_table[i];
373 return op_p; 348 return op_p;
374} 349}
375 350
376static void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) { 351static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
377 int i; 352{
353 int i = sysrq_key_table_key2index(key);
378 354
379 i = sysrq_key_table_key2index(key);
380 if (i != -1) 355 if (i != -1)
381 sysrq_key_table[i] = op_p; 356 sysrq_key_table[i] = op_p;
382} 357}
383 358
384/* 359/*
385 * This is the non-locking version of handle_sysrq 360 * This is the non-locking version of handle_sysrq. It must/can only be called
386 * It must/can only be called by sysrq key handlers, 361 * by sysrq key handlers, as they are inside of the lock
387 * as they are inside of the lock
388 */ 362 */
389 363void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty,
390void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, int check_mask) 364 int check_mask)
391{ 365{
392 struct sysrq_key_op *op_p; 366 struct sysrq_key_op *op_p;
393 int orig_log_level; 367 int orig_log_level;
394 int i, j; 368 int i;
395 unsigned long flags; 369 unsigned long flags;
396 370
397 spin_lock_irqsave(&sysrq_key_table_lock, flags); 371 spin_lock_irqsave(&sysrq_key_table_lock, flags);
@@ -401,26 +375,34 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, in
401 375
402 op_p = __sysrq_get_key_op(key); 376 op_p = __sysrq_get_key_op(key);
403 if (op_p) { 377 if (op_p) {
404 /* Should we check for enabled operations (/proc/sysrq-trigger should not) 378 /*
405 * and is the invoked operation enabled? */ 379 * Should we check for enabled operations (/proc/sysrq-trigger
380 * should not) and is the invoked operation enabled?
381 */
406 if (!check_mask || sysrq_enabled == 1 || 382 if (!check_mask || sysrq_enabled == 1 ||
407 (sysrq_enabled & op_p->enable_mask)) { 383 (sysrq_enabled & op_p->enable_mask)) {
408 printk ("%s\n", op_p->action_msg); 384 printk("%s\n", op_p->action_msg);
409 console_loglevel = orig_log_level; 385 console_loglevel = orig_log_level;
410 op_p->handler(key, pt_regs, tty); 386 op_p->handler(key, pt_regs, tty);
411 } 387 } else {
412 else
413 printk("This sysrq operation is disabled.\n"); 388 printk("This sysrq operation is disabled.\n");
389 }
414 } else { 390 } else {
415 printk("HELP : "); 391 printk("HELP : ");
416 /* Only print the help msg once per handler */ 392 /* Only print the help msg once per handler */
417 for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++) 393 for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) {
418 if (sysrq_key_table[i]) { 394 if (sysrq_key_table[i]) {
419 for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++); 395 int j;
420 if (j == i) 396
421 printk ("%s ", sysrq_key_table[i]->help_msg); 397 for (j = 0; sysrq_key_table[i] !=
398 sysrq_key_table[j]; j++)
399 ;
400 if (j != i)
401 continue;
402 printk("%s ", sysrq_key_table[i]->help_msg);
403 }
422 } 404 }
423 printk ("\n"); 405 printk("\n");
424 console_loglevel = orig_log_level; 406 console_loglevel = orig_log_level;
425 } 407 }
426 spin_unlock_irqrestore(&sysrq_key_table_lock, flags); 408 spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
@@ -430,16 +412,17 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, in
430 * This function is called by the keyboard handler when SysRq is pressed 412 * This function is called by the keyboard handler when SysRq is pressed
431 * and any other keycode arrives. 413 * and any other keycode arrives.
432 */ 414 */
433
434void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) 415void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
435{ 416{
436 if (!sysrq_enabled) 417 if (!sysrq_enabled)
437 return; 418 return;
438 __handle_sysrq(key, pt_regs, tty, 1); 419 __handle_sysrq(key, pt_regs, tty, 1);
439} 420}
421EXPORT_SYMBOL(handle_sysrq);
440 422
441static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, 423static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
442 struct sysrq_key_op *remove_op_p) { 424 struct sysrq_key_op *remove_op_p)
425{
443 426
444 int retval; 427 int retval;
445 unsigned long flags; 428 unsigned long flags;
@@ -452,7 +435,6 @@ static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
452 retval = -1; 435 retval = -1;
453 } 436 }
454 spin_unlock_irqrestore(&sysrq_key_table_lock, flags); 437 spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
455
456 return retval; 438 return retval;
457} 439}
458 440
@@ -460,12 +442,10 @@ int register_sysrq_key(int key, struct sysrq_key_op *op_p)
460{ 442{
461 return __sysrq_swap_key_ops(key, op_p, NULL); 443 return __sysrq_swap_key_ops(key, op_p, NULL);
462} 444}
445EXPORT_SYMBOL(register_sysrq_key);
463 446
464int unregister_sysrq_key(int key, struct sysrq_key_op *op_p) 447int unregister_sysrq_key(int key, struct sysrq_key_op *op_p)
465{ 448{
466 return __sysrq_swap_key_ops(key, NULL, op_p); 449 return __sysrq_swap_key_ops(key, NULL, op_p);
467} 450}
468
469EXPORT_SYMBOL(handle_sysrq);
470EXPORT_SYMBOL(register_sysrq_key);
471EXPORT_SYMBOL(unregister_sysrq_key); 451EXPORT_SYMBOL(unregister_sysrq_key);