From patchwork Thu Sep 11 13:37:43 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 37253 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ob0-f198.google.com (mail-ob0-f198.google.com [209.85.214.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id CAFFC20491 for ; Thu, 11 Sep 2014 13:38:01 +0000 (UTC) Received: by mail-ob0-f198.google.com with SMTP id wp18sf95889655obc.1 for ; Thu, 11 Sep 2014 06:38:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=twYoRqd0Hzi7+gEElx25Ywizz8AhdxTUDrLv320KQTw=; b=hYWnKmKGVeGvsESaD/qt5sq3pWQuvjoZLo4NZfweVsil9ZpsIl8DFF0KQgCjqY0cek g+LTBglyR0PhF+QjA3ah4g7+BgFlJItb3Y4veVLf43xoFyu221i2ezFBI98WJC61XnTg IuAMoNkjxb3rjnDkvAuf6j4iCs2YqcQrtNMiyLMuQ6dI5HXW00X7S6iTGUTGfAn4UyK5 NeS8Nnl9ENmw6KBa201X6Qv0mtUHtNzammIIKggglL98x1JHvuA8hWyuUp8oyCb+WQP9 mrVN+ilKzLtB/aoddbyN8aJcoMaz1V52cddaiuX/f5KakA67jhB7hddjsyZwZDVpjJnq 0Duw== X-Gm-Message-State: ALoCoQmFWHVGOrss7jjyEG0Ypd68UBnuc9zO1aPWGSM0HYR8D5l4zyYc+IAXr4hoHTjaBsJuDvjv X-Received: by 10.182.60.36 with SMTP id e4mr500224obr.3.1410442681367; Thu, 11 Sep 2014 06:38:01 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.43.181 with SMTP id e50ls176204qga.20.gmail; Thu, 11 Sep 2014 06:38:01 -0700 (PDT) X-Received: by 10.220.163.130 with SMTP id a2mr676999vcy.52.1410442681245; Thu, 11 Sep 2014 06:38:01 -0700 (PDT) Received: from mail-vc0-f170.google.com (mail-vc0-f170.google.com [209.85.220.170]) by mx.google.com with ESMTPS id w7si371113vcs.17.2014.09.11.06.38.01 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 11 Sep 2014 06:38:01 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.170 as permitted sender) client-ip=209.85.220.170; Received: by mail-vc0-f170.google.com with SMTP id hy4so5548223vcb.1 for ; Thu, 11 Sep 2014 06:38:01 -0700 (PDT) X-Received: by 10.52.3.40 with SMTP id 8mr581502vdz.24.1410442681142; Thu, 11 Sep 2014 06:38:01 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.221.45.67 with SMTP id uj3csp593243vcb; Thu, 11 Sep 2014 06:38:00 -0700 (PDT) X-Received: by 10.194.243.201 with SMTP id xa9mr1721348wjc.0.1410442680173; Thu, 11 Sep 2014 06:38:00 -0700 (PDT) Received: from mail-wg0-f48.google.com (mail-wg0-f48.google.com [74.125.82.48]) by mx.google.com with ESMTPS id g2si1403738wjx.123.2014.09.11.06.37.57 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 11 Sep 2014 06:37:58 -0700 (PDT) Received-SPF: pass (google.com: domain of daniel.thompson@linaro.org designates 74.125.82.48 as permitted sender) client-ip=74.125.82.48; Received: by mail-wg0-f48.google.com with SMTP id m15so5969494wgh.19 for ; Thu, 11 Sep 2014 06:37:57 -0700 (PDT) X-Received: by 10.194.78.100 with SMTP id a4mr1498471wjx.106.1410442675749; Thu, 11 Sep 2014 06:37:55 -0700 (PDT) Received: from sundance.lan (cpc4-aztw19-0-0-cust157.18-1.cable.virginm.net. [82.33.25.158]) by mx.google.com with ESMTPSA id ub19sm6004538wib.9.2014.09.11.06.37.54 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 11 Sep 2014 06:37:54 -0700 (PDT) From: Daniel Thompson To: Greg Kroah-Hartman Cc: Daniel Thompson , linux-kernel@vger.kernel.org, patches@linaro.org, linaro-kernel@lists.linaro.org, Jiri Slaby , linux-serial@vger.kernel.org Subject: [RFC PATCH] serial: Emulate break using control characters Date: Thu, 11 Sep 2014 14:37:43 +0100 Message-Id: <1410442663-10068-1-git-send-email-daniel.thompson@linaro.org> X-Mailer: git-send-email 1.9.3 X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: daniel.thompson@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.170 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Currently the magic SysRq functions can accessed by sending a break on the serial port. Unfortunately some networked serial proxies make it difficult to send a break meaning SysRq functions cannot be used. This patch provides a workaround by allowing the (fairly unlikely) sequence of ^B^R^K characters to emulate a real break. This approach is very nearly as robust as normal sysrq/break handling because all trigger recognition happens during interrupt handling. Only major difference is that to emulate a break we must enter the ISR four times (instead of twice) and manage an extra byte of state. No means is provided to escape the trigger sequence (and pass ^B^R^K to the underlying process) however the sequence is proved reasonably pretty collision resistant in practice. The most significant consequence is that ^B and ^B^R are delayed until a new character is observed. The most significant collision I am aware of is with emacs-like backward-char bindings (^B) because the character movement will become lumpy (two characters every two key presses rather than one character per key press). Arrow keys or ^B^B^F provide workarounds. Special note for tmux users: tmux defaults to using ^B as its escape character but does not have a default binding for ^B^R. Likewise tmux had no visual indicator showing the beginning of break sequence meaning delayed the delivery of ^B is not observable. Thus serial break emulation does not interfere with the use of tmux's default key bindings. Signed-off-by: Daniel Thompson Cc: Greg Kroah-Hartman Cc: Jiri Slaby Cc: linux-serial@vger.kernel.org --- Notes: I've been sitting on this patch for a long time. However I realized today just how frequently I end up using this and wondered if perhaps I am not alone. Yes! How did you guess? As it happens I do have quite a few broken network to UART interfaces. include/linux/serial_core.h | 83 +++++++++++++++++++++++++++++++++++---------- lib/Kconfig.debug | 15 ++++++++ 2 files changed, 80 insertions(+), 18 deletions(-) -- 1.9.3 diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index cf3a1e7..dffb188 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -150,6 +150,9 @@ struct uart_port { struct console *cons; /* struct console, if any */ #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ) unsigned long sysrq; /* sysrq timeout */ +#ifdef CONFIG_MAGIC_SYSRQ_BREAK_EMULATION + char sysrq_emul; /* sysrq break emulation */ +#endif #endif upf_t flags; @@ -364,24 +367,6 @@ extern void uart_handle_cts_change(struct uart_port *uport, extern void uart_insert_char(struct uart_port *port, unsigned int status, unsigned int overrun, unsigned int ch, unsigned int flag); -#ifdef SUPPORT_SYSRQ -static inline int -uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) -{ - if (port->sysrq) { - if (ch && time_before(jiffies, port->sysrq)) { - handle_sysrq(ch); - port->sysrq = 0; - return 1; - } - port->sysrq = 0; - } - return 0; -} -#else -#define uart_handle_sysrq_char(port,ch) ({ (void)port; 0; }) -#endif - /* * We do the SysRQ and SAK checking like this... */ @@ -406,6 +391,68 @@ static inline int uart_handle_break(struct uart_port *port) return 0; } +#if defined(SUPPORT_SYSRQ) && defined(CONFIG_MAGIC_SYSRQ_BREAK_EMULATION) +/* + * Emulate a break if we are the serial console and receive ^B, ^R, ^K. + */ +static inline int +uart_handle_sysrq_break_emulation(struct uart_port *port, unsigned int ch) +{ + const unsigned int ctrlb = 'B' & 31; + const unsigned int ctrlr = 'R' & 31; + const unsigned int ctrlk = 'K' & 31; + + if (uart_console(port)) { + if ((port->sysrq_emul == 0 && ch == ctrlb) || + (port->sysrq_emul == ctrlb && ch == ctrlr)) { + /* for either of the first two trigger characters + * update the state variable and move on. + */ + port->sysrq_emul = ch; + return 1; + } else if (port->sysrq_emul == ctrlr && ch == ctrlk && + uart_handle_break(port)) { + /* the break has already been emulated whilst + * evaluating the condition, tidy up and move on + */ + port->sysrq_emul = 0; + return 1; + } + } + + if (port->sysrq_emul) { + /* received a partial (false) trigger, tidy up and move on */ + uart_insert_char(port, 0, 0, ctrlb, TTY_NORMAL); + if (port->sysrq_emul == ctrlr) + uart_insert_char(port, 0, 0, ctrlr, TTY_NORMAL); + port->sysrq_emul = 0; + } + + return 0; +} +#else +#define uart_handle_sysrq_break_emulation(port, ch) ({ (void)port; 0; }) +#endif + +#ifdef SUPPORT_SYSRQ +static inline int +uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) +{ + if (port->sysrq) { + if (ch && time_before(jiffies, port->sysrq)) { + handle_sysrq(ch); + port->sysrq = 0; + return 1; + } + port->sysrq = 0; + } + + return uart_handle_sysrq_break_emulation(port, ch); +} +#else +#define uart_handle_sysrq_char(port,ch) ({ (void)port; 0; }) +#endif + /* * UART_ENABLE_MS - determine if port should enable modem status irqs */ diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index a285900..bcd9cf5 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -345,6 +345,21 @@ config MAGIC_SYSRQ_DEFAULT_ENABLE This may be set to 1 or 0 to enable or disable them all, or to a bitmask as described in Documentation/sysrq.txt. +config MAGIC_SYSRQ_BREAK_EMULATION + bool "Enable magic SysRq serial break emulation" + depends on MAGIC_SYSRQ && SERIAL_CORE_CONSOLE + default n + help + If you say Y here, then you can use the character sequence ^B^R^K + to simulate a BREAK on the serial console. This is useful if for + some reason you cannot send a BREAK to your console's serial port. + For example, if you have a serial device server that cannot + send a BREAK. Enabling this feature can delay the delivery of + characters to the TTY because the ^B and a subsequent ^R will be + delayed until we know what the next character is. + + If unsure, say N. + config DEBUG_KERNEL bool "Kernel debugging" help