blob: 791c1133cf4512290c20cac2ad068a807c8e0653 [file] [log] [blame]
From 7d52be76b2415eda9aecd85404f6e3fcd42a5432 Mon Sep 17 00:00:00 2001
From: Sameer Nanda <snanda@chromium.org>
Date: Mon, 6 Aug 2012 09:16:21 -0700
Subject: [PATCH] CHROMIUM: sysrq: Added Chrome OS specific 'x' key
On Chrome OS systems the magic sysrq x key will cause the following to
happen:
- show processes in blocked state
- emergency file sync
- crash the system
This key combination can be used in the field by users to cause the
system to crash so that crash dumps can be collected to help debug UI
freeze issues.
BUG=chromium-os:33249
TEST=First "echo 0x1000 > /proc/sys/kernel/sysrq", then do the two tests
below:
1. Alt-F10-x should cause the system to crash. Looks for kcrash logs
under /var/spool/crash when the system reboots.
2. All other magic sysrq operation aside from alt-F10-x should be
ineffective.
Change-Id: I62d0a7f0028c072928be0125da4e069bafa5d88c
Signed-off-by: Sameer Nanda <snanda@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/29316
[rebase66(tzungbi):
Revised commit message.
Squashed:
CHROMIUM: sysrq: treat F10 as magic sysrq key
(https://gerrit.chromium.org/gerrit/29110)
CHROMIUM: sysrq: clear sysrq->active state on sysrq release
(https://chromium-review.googlesource.com/264198)
CHROMIUM: sysrq: Use KEY_VOLUMEUP for sysrq key
(https://crrev.com/c/2163131)
FIXUP: CHROMIUM: sysrq: Added Chrome OS specific x key
]
Signed-off-by: Tzung-Bi Shih <tzungbi@chromium.org>
---
drivers/tty/sysrq.c | 69 +++++++++++++++++++++++++++++++++++++++++--
include/linux/sysrq.h | 1 +
2 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index e5974b8239c9904abbc15c1b658380bd800426b8..c28adc096726076cff702a4d8dfae1cb50c54d42 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -51,6 +51,7 @@
#include <linux/syscalls.h>
#include <linux/of.h>
#include <linux/rcupdate.h>
+#include <linux/delay.h>
#include <asm/ptrace.h>
#include <asm/irq_regs.h>
@@ -461,6 +462,64 @@ static struct sysrq_key_op sysrq_replay_logs_op = {
.enable_mask = SYSRQ_ENABLE_DUMP,
};
+/* send a signal to a process named comm if it has a certain parent */
+/* if parent is NULL, send to the first matching process */
+static void sysrq_x_cros_signal_process(char *comm, char *parent, int sig)
+{
+ struct task_struct *p;
+
+ read_lock(&tasklist_lock);
+ for_each_process(p) {
+ if (p->flags & (PF_KTHREAD | PF_EXITING))
+ continue;
+ if (is_global_init(p))
+ continue;
+ if (strncmp(p->comm, comm, TASK_COMM_LEN))
+ continue;
+ if (parent && strncmp(p->parent->comm, parent, TASK_COMM_LEN))
+ continue;
+
+ printk(KERN_INFO "%s: signal %d %s pid %u tgid %u\n",
+ __func__, sig, comm, p->pid, p->tgid);
+ do_send_sig_info(sig, SEND_SIG_PRIV, p, PIDTYPE_MAX);
+ }
+ read_unlock(&tasklist_lock);
+}
+
+/* how many seconds do we wait for subsequent keypresses after the first */
+#define CROS_SYSRQ_WAIT 20
+
+static void sysrq_handle_cros_xkey(u8 key)
+{
+ static unsigned long first_jiffies = INITIAL_JIFFIES - CROS_SYSRQ_WAIT * HZ;
+ static unsigned int xkey_iteration;
+
+ if (time_after(jiffies, first_jiffies + CROS_SYSRQ_WAIT * HZ)) {
+ first_jiffies = jiffies;
+ xkey_iteration = 0;
+ } else {
+ xkey_iteration++;
+ }
+
+ if (!xkey_iteration) {
+ sysrq_x_cros_signal_process("chrome", "session_manager",
+ SIGABRT);
+ } else {
+ sysrq_handle_showstate_blocked(key);
+ sysrq_handle_sync(key);
+ /* Delay for a bit to give time for sync to complete */
+ mdelay(1000);
+ panic("ChromeOS X Key");
+ }
+}
+
+static struct sysrq_key_op sysrq_cros_xkey = {
+ .handler = sysrq_handle_cros_xkey,
+ .help_msg = "Cros-dump-and-crash",
+ .action_msg = "Cros dump and crash",
+ .enable_mask = SYSRQ_ENABLE_CROS_XKEY,
+};
+
/* Key Operations table and lock */
static DEFINE_SPINLOCK(sysrq_key_table_lock);
@@ -509,7 +568,8 @@ static const struct sysrq_key_op *sysrq_key_table[62] = {
/* x: May be registered on mips for TLB dump */
/* x: May be registered on ppc/powerpc for xmon */
/* x: May be registered on sparc64 for global PMU dump */
- NULL, /* x */
+ /* x: On Chrome OS, this is the dump and crash key */
+ &sysrq_cros_xkey, /* x */
/* y: May be registered on sparc64 for global register dump */
NULL, /* y */
&sysrq_ftrace_dump_op, /* z */
@@ -861,7 +921,12 @@ static bool sysrq_handle_keypress(struct sysrq_state *sysrq,
break;
case KEY_SYSRQ:
- if (value == 1 && sysrq->alt != KEY_RESERVED) {
+ case KEY_F10:
+ case KEY_VOLUMEUP:
+ if (!value) {
+ /* sysrq is being released */
+ sysrq->active = false;
+ } else if (value == 1 && sysrq->alt != KEY_RESERVED) {
sysrq->active = true;
sysrq->alt_use = sysrq->alt;
/* either RESERVED (for released) or actual code */
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
index bdca467ebb77355c62dbd74b7f547a70627e0325..e78da8c37adb4d0dc810924bdba4a6afed5e2e39 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -28,6 +28,7 @@
#define SYSRQ_ENABLE_SIGNAL 0x0040
#define SYSRQ_ENABLE_BOOT 0x0080
#define SYSRQ_ENABLE_RTNICE 0x0100
+#define SYSRQ_ENABLE_CROS_XKEY 0x1000
struct sysrq_key_op {
void (* const handler)(u8);
--
2.45.1.288.g0e0cd299f1-goog