^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Linux Magic System Request Key Hacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * based on ideas by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * (c) 2000 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * overhauled to use key registration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * based upon discusions in irc://irc.openprojects.net/#kernelnewbies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (c) 2010 Dmitry Torokhov
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Input handler conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/sched/rt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/sched/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/sched/task.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/kdev_t.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/sysrq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/kbd_kern.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/nmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/quotaops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/writeback.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/swap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/vt_kern.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/hrtimer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/oom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/rcupdate.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <asm/irq_regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Whether we react on sysrq keys or just ignore them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static int __read_mostly sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static bool __read_mostly sysrq_always_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static bool sysrq_on(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return sysrq_enabled || sysrq_always_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * sysrq_mask - Getter for sysrq_enabled mask.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * Return: 1 if sysrq is always enabled, enabled sysrq_key_op mask otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int sysrq_mask(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (sysrq_always_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return sysrq_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) EXPORT_SYMBOL_GPL(sysrq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * A value of 1 means 'all', other nonzero values are an op mask:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static bool sysrq_on_mask(int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return sysrq_always_enabled ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) sysrq_enabled == 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) (sysrq_enabled & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int __init sysrq_always_enabled_setup(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) sysrq_always_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) pr_info("sysrq always enabled.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) __setup("sysrq_always_enabled", sysrq_always_enabled_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void sysrq_handle_loglevel(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) i = key - '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) console_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) pr_info("Loglevel set to %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) console_loglevel = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static const struct sysrq_key_op sysrq_loglevel_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .handler = sysrq_handle_loglevel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .help_msg = "loglevel(0-9)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .action_msg = "Changing Loglevel",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .enable_mask = SYSRQ_ENABLE_LOG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #ifdef CONFIG_VT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static void sysrq_handle_SAK(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) schedule_work(SAK_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static const struct sysrq_key_op sysrq_SAK_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .handler = sysrq_handle_SAK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .help_msg = "sak(k)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .action_msg = "SAK",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .enable_mask = SYSRQ_ENABLE_KEYBOARD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define sysrq_SAK_op (*(const struct sysrq_key_op *)NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #ifdef CONFIG_VT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void sysrq_handle_unraw(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) vt_reset_unicode(fg_console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static const struct sysrq_key_op sysrq_unraw_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .handler = sysrq_handle_unraw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .help_msg = "unraw(r)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .action_msg = "Keyboard mode set to system default",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .enable_mask = SYSRQ_ENABLE_KEYBOARD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define sysrq_unraw_op (*(const struct sysrq_key_op *)NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #endif /* CONFIG_VT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static void sysrq_handle_crash(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* release the RCU read lock before crashing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) panic("sysrq triggered crash\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static const struct sysrq_key_op sysrq_crash_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .handler = sysrq_handle_crash,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .help_msg = "crash(c)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .action_msg = "Trigger a crash",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .enable_mask = SYSRQ_ENABLE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static void sysrq_handle_reboot(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) lockdep_off();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) local_irq_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) emergency_restart();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static const struct sysrq_key_op sysrq_reboot_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .handler = sysrq_handle_reboot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .help_msg = "reboot(b)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .action_msg = "Resetting",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .enable_mask = SYSRQ_ENABLE_BOOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) const struct sysrq_key_op *__sysrq_reboot_op = &sysrq_reboot_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static void sysrq_handle_sync(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) emergency_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static const struct sysrq_key_op sysrq_sync_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .handler = sysrq_handle_sync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .help_msg = "sync(s)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .action_msg = "Emergency Sync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .enable_mask = SYSRQ_ENABLE_SYNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static void sysrq_handle_show_timers(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) sysrq_timer_list_show();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static const struct sysrq_key_op sysrq_show_timers_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .handler = sysrq_handle_show_timers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .help_msg = "show-all-timers(q)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .action_msg = "Show clockevent devices & pending hrtimers (no others)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static void sysrq_handle_mountro(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) emergency_remount();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static const struct sysrq_key_op sysrq_mountro_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .handler = sysrq_handle_mountro,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .help_msg = "unmount(u)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .action_msg = "Emergency Remount R/O",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .enable_mask = SYSRQ_ENABLE_REMOUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #ifdef CONFIG_LOCKDEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static void sysrq_handle_showlocks(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) debug_show_all_locks();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static const struct sysrq_key_op sysrq_showlocks_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .handler = sysrq_handle_showlocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .help_msg = "show-all-locks(d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .action_msg = "Show Locks Held",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #define sysrq_showlocks_op (*(const struct sysrq_key_op *)NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static DEFINE_RAW_SPINLOCK(show_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static void showacpu(void *dummy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* Idle CPUs have no interesting backtrace. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (idle_cpu(smp_processor_id()))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) raw_spin_lock_irqsave(&show_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) pr_info("CPU%d:\n", smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) show_stack(NULL, NULL, KERN_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) raw_spin_unlock_irqrestore(&show_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static void sysrq_showregs_othercpus(struct work_struct *dummy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) smp_call_function(showacpu, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static void sysrq_handle_showallcpus(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * Fall back to the workqueue based printing if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * backtrace printing did not succeed or the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * architecture has no support for it:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!trigger_all_cpu_backtrace()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct pt_regs *regs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (in_irq())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) regs = get_irq_regs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) pr_info("CPU%d:\n", smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) show_regs(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) schedule_work(&sysrq_showallcpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static const struct sysrq_key_op sysrq_showallcpus_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .handler = sysrq_handle_showallcpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .help_msg = "show-backtrace-all-active-cpus(l)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) .action_msg = "Show backtrace of all active CPUs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) .enable_mask = SYSRQ_ENABLE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static void sysrq_handle_showregs(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct pt_regs *regs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (in_irq())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) regs = get_irq_regs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) show_regs(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) perf_event_print_debug();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static const struct sysrq_key_op sysrq_showregs_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .handler = sysrq_handle_showregs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .help_msg = "show-registers(p)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .action_msg = "Show Regs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .enable_mask = SYSRQ_ENABLE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static void sysrq_handle_showstate(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) show_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) show_workqueue_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static const struct sysrq_key_op sysrq_showstate_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .handler = sysrq_handle_showstate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) .help_msg = "show-task-states(t)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .action_msg = "Show State",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .enable_mask = SYSRQ_ENABLE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static void sysrq_handle_showstate_blocked(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) show_state_filter(TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static const struct sysrq_key_op sysrq_showstate_blocked_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .handler = sysrq_handle_showstate_blocked,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) .help_msg = "show-blocked-tasks(w)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) .action_msg = "Show Blocked State",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) .enable_mask = SYSRQ_ENABLE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) #ifdef CONFIG_TRACING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) #include <linux/ftrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static void sysrq_ftrace_dump(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) ftrace_dump(DUMP_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static const struct sysrq_key_op sysrq_ftrace_dump_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .handler = sysrq_ftrace_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .help_msg = "dump-ftrace-buffer(z)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .action_msg = "Dump ftrace buffer",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .enable_mask = SYSRQ_ENABLE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) #define sysrq_ftrace_dump_op (*(const struct sysrq_key_op *)NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static void sysrq_handle_showmem(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) show_mem(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static const struct sysrq_key_op sysrq_showmem_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) .handler = sysrq_handle_showmem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .help_msg = "show-memory-usage(m)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .action_msg = "Show Memory",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) .enable_mask = SYSRQ_ENABLE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * Signal sysrq helper function. Sends a signal to all user processes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static void send_sig_all(int sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct task_struct *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) read_lock(&tasklist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) for_each_process(p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (p->flags & PF_KTHREAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (is_global_init(p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) do_send_sig_info(sig, SEND_SIG_PRIV, p, PIDTYPE_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) read_unlock(&tasklist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static void sysrq_handle_term(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) send_sig_all(SIGTERM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) console_loglevel = CONSOLE_LOGLEVEL_DEBUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static const struct sysrq_key_op sysrq_term_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) .handler = sysrq_handle_term,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .help_msg = "terminate-all-tasks(e)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .action_msg = "Terminate All Tasks",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) .enable_mask = SYSRQ_ENABLE_SIGNAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static void moom_callback(struct work_struct *ignored)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) const gfp_t gfp_mask = GFP_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct oom_control oc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .zonelist = node_zonelist(first_memory_node, gfp_mask),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .nodemask = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .memcg = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) .gfp_mask = gfp_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) .order = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) mutex_lock(&oom_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (!out_of_memory(&oc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) pr_info("OOM request ignored. No task eligible\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) mutex_unlock(&oom_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static DECLARE_WORK(moom_work, moom_callback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static void sysrq_handle_moom(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) schedule_work(&moom_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static const struct sysrq_key_op sysrq_moom_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .handler = sysrq_handle_moom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .help_msg = "memory-full-oom-kill(f)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) .action_msg = "Manual OOM execution",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) .enable_mask = SYSRQ_ENABLE_SIGNAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static void sysrq_handle_thaw(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) emergency_thaw_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static const struct sysrq_key_op sysrq_thaw_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .handler = sysrq_handle_thaw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .help_msg = "thaw-filesystems(j)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) .action_msg = "Emergency Thaw of all frozen filesystems",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) .enable_mask = SYSRQ_ENABLE_SIGNAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static void sysrq_handle_kill(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) send_sig_all(SIGKILL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) console_loglevel = CONSOLE_LOGLEVEL_DEBUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static const struct sysrq_key_op sysrq_kill_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .handler = sysrq_handle_kill,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) .help_msg = "kill-all-tasks(i)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) .action_msg = "Kill All Tasks",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .enable_mask = SYSRQ_ENABLE_SIGNAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static void sysrq_handle_unrt(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) normalize_rt_tasks();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static const struct sysrq_key_op sysrq_unrt_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) .handler = sysrq_handle_unrt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) .help_msg = "nice-all-RT-tasks(n)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) .action_msg = "Nice All RT Tasks",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) .enable_mask = SYSRQ_ENABLE_RTNICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* Key Operations table and lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static DEFINE_SPINLOCK(sysrq_key_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static const struct sysrq_key_op *sysrq_key_table[62] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) &sysrq_loglevel_op, /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) &sysrq_loglevel_op, /* 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) &sysrq_loglevel_op, /* 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) &sysrq_loglevel_op, /* 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) &sysrq_loglevel_op, /* 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) &sysrq_loglevel_op, /* 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) &sysrq_loglevel_op, /* 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) &sysrq_loglevel_op, /* 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) &sysrq_loglevel_op, /* 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) &sysrq_loglevel_op, /* 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * a: Don't use for system provided sysrqs, it is handled specially on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * sparc and will never arrive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) NULL, /* a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) &sysrq_reboot_op, /* b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) &sysrq_crash_op, /* c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) &sysrq_showlocks_op, /* d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) &sysrq_term_op, /* e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) &sysrq_moom_op, /* f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* g: May be registered for the kernel debugger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) NULL, /* g */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) NULL, /* h - reserved for help */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) &sysrq_kill_op, /* i */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) #ifdef CONFIG_BLOCK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) &sysrq_thaw_op, /* j */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) NULL, /* j */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) &sysrq_SAK_op, /* k */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) &sysrq_showallcpus_op, /* l */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) NULL, /* l */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) &sysrq_showmem_op, /* m */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) &sysrq_unrt_op, /* n */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* o: This will often be registered as 'Off' at init time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) NULL, /* o */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) &sysrq_showregs_op, /* p */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) &sysrq_show_timers_op, /* q */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) &sysrq_unraw_op, /* r */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) &sysrq_sync_op, /* s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) &sysrq_showstate_op, /* t */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) &sysrq_mountro_op, /* u */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* v: May be registered for frame buffer console restore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) NULL, /* v */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) &sysrq_showstate_blocked_op, /* w */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /* x: May be registered on mips for TLB dump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* x: May be registered on ppc/powerpc for xmon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /* x: May be registered on sparc64 for global PMU dump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) NULL, /* x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /* y: May be registered on sparc64 for global register dump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) NULL, /* y */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) &sysrq_ftrace_dump_op, /* z */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) NULL, /* A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) NULL, /* B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) NULL, /* C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) NULL, /* D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) NULL, /* E */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) NULL, /* F */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) NULL, /* G */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) NULL, /* H */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) NULL, /* I */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) NULL, /* J */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) NULL, /* K */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) NULL, /* L */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) NULL, /* M */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) NULL, /* N */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) NULL, /* O */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) NULL, /* P */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) NULL, /* Q */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) NULL, /* R */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) NULL, /* S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) NULL, /* T */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) NULL, /* U */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) NULL, /* V */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) NULL, /* W */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) NULL, /* X */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) NULL, /* Y */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) NULL, /* Z */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* key2index calculation, -1 on invalid index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int sysrq_key_table_key2index(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if ((key >= '0') && (key <= '9'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) retval = key - '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) else if ((key >= 'a') && (key <= 'z'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) retval = key + 10 - 'a';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) else if ((key >= 'A') && (key <= 'Z'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) retval = key + 36 - 'A';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) retval = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * get and put functions for the table, exposed to modules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static const struct sysrq_key_op *__sysrq_get_key_op(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) const struct sysrq_key_op *op_p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) i = sysrq_key_table_key2index(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (i != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) op_p = sysrq_key_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return op_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static void __sysrq_put_key_op(int key, const struct sysrq_key_op *op_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) int i = sysrq_key_table_key2index(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (i != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) sysrq_key_table[i] = op_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) void __handle_sysrq(int key, bool check_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) const struct sysrq_key_op *op_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) int orig_log_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) int orig_suppress_printk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) orig_suppress_printk = suppress_printk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) suppress_printk = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) rcu_sysrq_start();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * Raise the apparent loglevel to maximum so that the sysrq header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * is shown to provide the user with positive feedback. We do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * simply emit this at KERN_EMERG as that would change message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * routing in the consumers of /proc/kmsg.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) orig_log_level = console_loglevel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) console_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) op_p = __sysrq_get_key_op(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (op_p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * Should we check for enabled operations (/proc/sysrq-trigger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * should not) and is the invoked operation enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) pr_info("%s\n", op_p->action_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) console_loglevel = orig_log_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) op_p->handler(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) pr_info("This sysrq operation is disabled.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) console_loglevel = orig_log_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) pr_info("HELP : ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* Only print the help msg once per handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (sysrq_key_table[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) for (j = 0; sysrq_key_table[i] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) sysrq_key_table[j]; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (j != i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) pr_cont("%s ", sysrq_key_table[i]->help_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) pr_cont("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) console_loglevel = orig_log_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) rcu_sysrq_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) suppress_printk = orig_suppress_printk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) void handle_sysrq(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (sysrq_on())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) __handle_sysrq(key, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) EXPORT_SYMBOL(handle_sysrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) #ifdef CONFIG_INPUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static int sysrq_reset_downtime_ms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* Simple translation table for the SysRq keys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static const unsigned char sysrq_xlate[KEY_CNT] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) "\r\000/"; /* 0x60 - 0x6f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct sysrq_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct input_handle handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct work_struct reinject_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) unsigned int alt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) unsigned int alt_use;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) unsigned int shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) unsigned int shift_use;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) bool active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) bool need_reinject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) bool reinjecting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /* reset sequence handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) bool reset_canceled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) bool reset_requested;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) unsigned long reset_keybit[BITS_TO_LONGS(KEY_CNT)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) int reset_seq_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) int reset_seq_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) int reset_seq_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct timer_list keyreset_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) #define SYSRQ_KEY_RESET_MAX 20 /* Should be plenty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) static unsigned short sysrq_reset_seq[SYSRQ_KEY_RESET_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) static unsigned int sysrq_reset_seq_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static unsigned int sysrq_reset_seq_version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) static void sysrq_parse_reset_sequence(struct sysrq_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) unsigned short key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) state->reset_seq_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) for (i = 0; i < sysrq_reset_seq_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) key = sysrq_reset_seq[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (key == KEY_RESERVED || key > KEY_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) __set_bit(key, state->reset_keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) state->reset_seq_len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (test_bit(key, state->key_down))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) state->reset_seq_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /* Disable reset until old keys are not released */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) state->reset_canceled = state->reset_seq_cnt != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) state->reset_seq_version = sysrq_reset_seq_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static void sysrq_do_reset(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct sysrq_state *state = from_timer(state, t, keyreset_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) state->reset_requested = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) orderly_reboot();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static void sysrq_handle_reset_request(struct sysrq_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (state->reset_requested)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) __handle_sysrq(sysrq_xlate[KEY_B], false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (sysrq_reset_downtime_ms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) mod_timer(&state->keyreset_timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) jiffies + msecs_to_jiffies(sysrq_reset_downtime_ms));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) sysrq_do_reset(&state->keyreset_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) static void sysrq_detect_reset_sequence(struct sysrq_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) unsigned int code, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (!test_bit(code, state->reset_keybit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * Pressing any key _not_ in reset sequence cancels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) * the reset sequence. Also cancelling the timer in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) * case additional keys were pressed after a reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) * has been requested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (value && state->reset_seq_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) state->reset_canceled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) del_timer(&state->keyreset_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) } else if (value == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * Key release - all keys in the reset sequence need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * to be pressed and held for the reset timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * to hold.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) del_timer(&state->keyreset_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (--state->reset_seq_cnt == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) state->reset_canceled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) } else if (value == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) /* key press, not autorepeat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (++state->reset_seq_cnt == state->reset_seq_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) !state->reset_canceled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) sysrq_handle_reset_request(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) static void sysrq_of_get_keyreset_config(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) u32 key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) const __be32 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) np = of_find_node_by_path("/chosen/linux,sysrq-reset-seq");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) pr_debug("No sysrq node found");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /* Reset in case a __weak definition was present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) sysrq_reset_seq_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) of_property_for_each_u32(np, "keyset", prop, p, key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (key == KEY_RESERVED || key > KEY_MAX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) sysrq_reset_seq_len == SYSRQ_KEY_RESET_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) sysrq_reset_seq[sysrq_reset_seq_len++] = (unsigned short)key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /* Get reset timeout if any. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) of_property_read_u32(np, "timeout-ms", &sysrq_reset_downtime_ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) static void sysrq_of_get_keyreset_config(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) static void sysrq_reinject_alt_sysrq(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) struct sysrq_state *sysrq =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) container_of(work, struct sysrq_state, reinject_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) struct input_handle *handle = &sysrq->handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) unsigned int alt_code = sysrq->alt_use;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (sysrq->need_reinject) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* we do not want the assignment to be reordered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) sysrq->reinjecting = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /* Simulate press and release of Alt + SysRq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) input_inject_event(handle, EV_KEY, alt_code, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) input_inject_event(handle, EV_KEY, KEY_SYSRQ, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) input_inject_event(handle, EV_SYN, SYN_REPORT, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) input_inject_event(handle, EV_KEY, KEY_SYSRQ, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) input_inject_event(handle, EV_KEY, alt_code, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) input_inject_event(handle, EV_SYN, SYN_REPORT, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) sysrq->reinjecting = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) static bool sysrq_handle_keypress(struct sysrq_state *sysrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) unsigned int code, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) bool was_active = sysrq->active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) bool suppress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) switch (code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) case KEY_LEFTALT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) case KEY_RIGHTALT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (!value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /* One of ALTs is being released */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (sysrq->active && code == sysrq->alt_use)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) sysrq->active = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) sysrq->alt = KEY_RESERVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) } else if (value != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) sysrq->alt = code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) sysrq->need_reinject = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) case KEY_LEFTSHIFT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) case KEY_RIGHTSHIFT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (!value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) sysrq->shift = KEY_RESERVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) else if (value != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) sysrq->shift = code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) case KEY_SYSRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (value == 1 && sysrq->alt != KEY_RESERVED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) sysrq->active = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) sysrq->alt_use = sysrq->alt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /* either RESERVED (for released) or actual code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) sysrq->shift_use = sysrq->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * If nothing else will be pressed we'll need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * to re-inject Alt-SysRq keysroke.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) sysrq->need_reinject = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * Pretend that sysrq was never pressed at all. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * is needed to properly handle KGDB which will try
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) * to release all keys after exiting debugger. If we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) * do not clear key bit it KGDB will end up sending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * release events for Alt and SysRq, potentially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * triggering print screen function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (sysrq->active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) clear_bit(KEY_SYSRQ, sysrq->handle.dev->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (sysrq->active && value && value != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) unsigned char c = sysrq_xlate[code];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) sysrq->need_reinject = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (sysrq->shift_use != KEY_RESERVED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) c = toupper(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) __handle_sysrq(c, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) suppress = sysrq->active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (!sysrq->active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) * See if reset sequence has changed since the last time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (sysrq->reset_seq_version != sysrq_reset_seq_version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) sysrq_parse_reset_sequence(sysrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * If we are not suppressing key presses keep track of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * keyboard state so we can release keys that have been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * pressed before entering SysRq mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) set_bit(code, sysrq->key_down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) clear_bit(code, sysrq->key_down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (was_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) schedule_work(&sysrq->reinject_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) /* Check for reset sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) sysrq_detect_reset_sequence(sysrq, code, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) } else if (value == 0 && test_and_clear_bit(code, sysrq->key_down)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) * Pass on release events for keys that was pressed before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * entering SysRq mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) suppress = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return suppress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) static bool sysrq_filter(struct input_handle *handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) unsigned int type, unsigned int code, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) struct sysrq_state *sysrq = handle->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) bool suppress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * Do not filter anything if we are in the process of re-injecting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) * Alt+SysRq combination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (sysrq->reinjecting)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) case EV_SYN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) suppress = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case EV_KEY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) suppress = sysrq_handle_keypress(sysrq, code, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) suppress = sysrq->active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) return suppress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) static int sysrq_connect(struct input_handler *handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct input_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) const struct input_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct sysrq_state *sysrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) sysrq = kzalloc(sizeof(struct sysrq_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (!sysrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) INIT_WORK(&sysrq->reinject_work, sysrq_reinject_alt_sysrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) sysrq->handle.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) sysrq->handle.handler = handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) sysrq->handle.name = "sysrq";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) sysrq->handle.private = sysrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) timer_setup(&sysrq->keyreset_timer, sysrq_do_reset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) error = input_register_handle(&sysrq->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) pr_err("Failed to register input sysrq handler, error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) error = input_open_device(&sysrq->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) pr_err("Failed to open input device, error %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) goto err_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) err_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) input_unregister_handle(&sysrq->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) kfree(sysrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) static void sysrq_disconnect(struct input_handle *handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct sysrq_state *sysrq = handle->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) input_close_device(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) cancel_work_sync(&sysrq->reinject_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) del_timer_sync(&sysrq->keyreset_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) input_unregister_handle(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) kfree(sysrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * We are matching on KEY_LEFTALT instead of KEY_SYSRQ because not all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * keyboards have SysRq key predefined and so user may add it to keymap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * later, but we expect all such keyboards to have left alt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) static const struct input_device_id sysrq_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) INPUT_DEVICE_ID_MATCH_KEYBIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) .evbit = { [BIT_WORD(EV_KEY)] = BIT_MASK(EV_KEY) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) .keybit = { [BIT_WORD(KEY_LEFTALT)] = BIT_MASK(KEY_LEFTALT) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) static struct input_handler sysrq_handler = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) .filter = sysrq_filter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) .connect = sysrq_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) .disconnect = sysrq_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) .name = "sysrq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) .id_table = sysrq_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) static inline void sysrq_register_handler(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) sysrq_of_get_keyreset_config();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) error = input_register_handler(&sysrq_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) pr_err("Failed to register input handler, error %d", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static inline void sysrq_unregister_handler(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) input_unregister_handler(&sysrq_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) static int sysrq_reset_seq_param_set(const char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) const struct kernel_param *kp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) error = kstrtoul(buffer, 0, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (val > KEY_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) *((unsigned short *)kp->arg) = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) sysrq_reset_seq_version++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) static const struct kernel_param_ops param_ops_sysrq_reset_seq = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) .get = param_get_ushort,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) .set = sysrq_reset_seq_param_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) #define param_check_sysrq_reset_seq(name, p) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) __param_check(name, p, unsigned short)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) * not really modular, but the easiest way to keep compat with existing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) * bootargs behaviour is to continue using module_param here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) &sysrq_reset_seq_len, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) module_param_named(sysrq_downtime_ms, sysrq_reset_downtime_ms, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) static inline void sysrq_register_handler(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) static inline void sysrq_unregister_handler(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) #endif /* CONFIG_INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) int sysrq_toggle_support(int enable_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) bool was_enabled = sysrq_on();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) sysrq_enabled = enable_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (was_enabled != sysrq_on()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (sysrq_on())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) sysrq_register_handler();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) sysrq_unregister_handler();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) EXPORT_SYMBOL_GPL(sysrq_toggle_support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) static int __sysrq_swap_key_ops(int key, const struct sysrq_key_op *insert_op_p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) const struct sysrq_key_op *remove_op_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) spin_lock(&sysrq_key_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (__sysrq_get_key_op(key) == remove_op_p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) __sysrq_put_key_op(key, insert_op_p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) retval = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) spin_unlock(&sysrq_key_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) * A concurrent __handle_sysrq either got the old op or the new op.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) * Wait for it to go away before returning, so the code for an old
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) * op is not freed (eg. on module unload) while it is in use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) int register_sysrq_key(int key, const struct sysrq_key_op *op_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) return __sysrq_swap_key_ops(key, op_p, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) EXPORT_SYMBOL(register_sysrq_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) int unregister_sysrq_key(int key, const struct sysrq_key_op *op_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) return __sysrq_swap_key_ops(key, NULL, op_p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) EXPORT_SYMBOL(unregister_sysrq_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) * writing 'C' to /proc/sysrq-trigger is like sysrq-C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (get_user(c, buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) __handle_sysrq(c, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) static const struct proc_ops sysrq_trigger_proc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) .proc_write = write_sysrq_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) .proc_lseek = noop_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) static void sysrq_init_procfs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (!proc_create("sysrq-trigger", S_IWUSR, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) &sysrq_trigger_proc_ops))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) pr_err("Failed to register proc interface\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) static inline void sysrq_init_procfs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) #endif /* CONFIG_PROC_FS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) static int __init sysrq_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) sysrq_init_procfs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (sysrq_on())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) sysrq_register_handler();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) device_initcall(sysrq_init);