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