OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [sysrq.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.