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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [sysrq.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* -*- linux-c -*-
2
 *
3
 *      $Id: sysrq.c,v 1.1.1.1 2004-04-15 01:59:18 phoenix 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
 
35
extern void reset_vc(unsigned int);
36
extern struct list_head super_blocks;
37
 
38
/* Whether we react on sysrq keys or just ignore them */
39
int sysrq_enabled = 1;
40
 
41
/* Machine specific power off function */
42
void (*sysrq_power_off)(void);
43
 
44
/* Loglevel sysrq handler */
45
static 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
}
53
static 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
62
static 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
}
68
static 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 */
77
static 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
}
82
static 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 */
90
static 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
}
94
static 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 */
106
static 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 */
137
static 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
 
189
volatile int emergency_sync_scheduled;
190
 
191
void 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
 
220
static 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
}
225
static struct sysrq_key_op sysrq_sync_op = {
226
        handler:        sysrq_handle_sync,
227
        help_msg:       "Sync",
228
        action_msg:     "Emergency Sync",
229
};
230
 
231
static 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
}
236
static 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
 
247
static 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
}
252
static struct sysrq_key_op sysrq_showregs_op = {
253
        handler:        sysrq_handle_showregs,
254
        help_msg:       "showPc",
255
        action_msg:     "Show Regs",
256
};
257
 
258
 
259
static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
260
                struct kbd_struct *kbd, struct tty_struct *tty) {
261
        show_state();
262
}
263
static struct sysrq_key_op sysrq_showstate_op = {
264
        handler:        sysrq_handle_showstate,
265
        help_msg:       "showTasks",
266
        action_msg:     "Show State",
267
};
268
 
269
 
270
static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
271
                struct kbd_struct *kbd, struct tty_struct *tty) {
272
        show_mem();
273
}
274
static 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 */
287
static 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
 
298
static 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
}
303
static struct sysrq_key_op sysrq_term_op = {
304
        handler:        sysrq_handle_term,
305
        help_msg:       "tErm",
306
        action_msg:     "Terminate All Tasks",
307
};
308
 
309
static 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
}
314
static 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 */
324
static spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED;
325
#define SYSRQ_KEY_TABLE_LENGTH 36
326
static 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 */
373
static __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
 
389
void __sysrq_lock_table (void) { spin_lock(&sysrq_key_table_lock); }
390
 
391
void __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
 
397
struct 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
 
406
void __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
 
419
void 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
 
435
void __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
 
467
EXPORT_SYMBOL(handle_sysrq);
468
EXPORT_SYMBOL(__handle_sysrq_nolock);
469
EXPORT_SYMBOL(__sysrq_lock_table);
470
EXPORT_SYMBOL(__sysrq_unlock_table);
471
EXPORT_SYMBOL(__sysrq_get_key_op);
472
EXPORT_SYMBOL(__sysrq_put_key_op);

powered by: WebSVN 2.1.0

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