linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] New console keyboard mode OFF
@ 2011-01-09  9:00 Arthur Taylor
  2011-01-11 14:34 ` Pavel Machek
  0 siblings, 1 reply; 4+ messages in thread
From: Arthur Taylor @ 2011-01-09  9:00 UTC (permalink / raw)
  To: linux-kernel

Hello

The current console keyboard situation can be improved by introducing
an "OFF" mode. All available modes for the console keyboard (RAW,
MEDIUMRAW, XLATE, and UNICODE) buffer key events in the current vt's
tty input. As recent Xorg releases no longer read input from the vt
there are two problems:

1) The tty input buffer eventually overflows because nothing is
reading it, triggering an infinite flush_to_ldisc() kworker loop.
2) If the vt's mode isn't changed to RAW or MEDIUMRAW, key events
remain translated by the kernel, causing shenanigans like pressing
Ctrl+C in Xterm would send SIGTERM to the X server.

Xorg fixed these problems in 2008 by always setting the vt to RAW mode
and making a handler call tcflush per keystroke if the
"AllowEmptyInput" option is enabled. I stumbled upon this issue when I
set my X server to not use AllowEmptyInput and manually defined input
devices using evdev. After a set amount of key presses in an X session
my system would experience 1000 wakeups/s, eating no real cpu time but
consuming three extra watts. While I appreciate that this is an
uncommon setup, the current solution is still sort-of hacky as it
means per-keystroke a key is simultaneously reported to userspace via
input device files as well as by the vt keyboard code, through the tty
and line descriptor until it gets to userspace where it is then
flushed by Xorg.

The addition of a new console keyboard mode "OFF" would remove the
need for the tcflush handler hack in Xorg and has the added benefit of
less code being run and less trips to userspace per key event. It is
simple to implement, either by returning early in the console input
handler's key event callback or by unregistering the console's input
handler while in the OFF mode VT. I have tried both methods with
success. Remember of course that the console keyboard mode is a per vt
setting.

The only complication is the way shift keys are handled (or modifiers
in X parlance.) As shift key up/down events are counted to get the
current shift state across all vts, disabling the input handler with a
shift key down makes things get out of sync with reality. Thus, the
key_down array (from which shift_down is calculated) should be cleared
when disabling the input handler. The other method of returning early
must still count shift key events. Note that neither SysRq, which uses
it's own input event handler, nor the Caps-Lock state, which is a
per-console thing, are affected by these changes.

The flush_to_ldisc() infinite kworker loop issue exists independent of
Xorg. It can be triggered by changing to a vt where nothing is reading
from it's input, like a log display, and mashing your keyboard for a
few minutes. Unlikely, but still present.

The Xorg commits I mentioned:
http://cgit.freedesktop.org/xorg/xserver/commit/?id=d936a4235c9625bd41569cef3452dd086284e0d7
http://cgit.freedesktop.org/xorg/xserver/commit/?id=446d9443cea31e493d05c939d0128a8116788468

Cheers
-Art


-- 
Arthur Taylor
art@ified.ca
taylora@uvic.ca

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC] New console keyboard mode OFF
  2011-01-09  9:00 [RFC] New console keyboard mode OFF Arthur Taylor
@ 2011-01-11 14:34 ` Pavel Machek
  2011-01-13 11:01   ` Arthur Taylor
  0 siblings, 1 reply; 4+ messages in thread
From: Pavel Machek @ 2011-01-11 14:34 UTC (permalink / raw)
  To: Arthur Taylor; +Cc: linux-kernel

Hi!

> The current console keyboard situation can be improved by introducing
> an "OFF" mode. All available modes for the console keyboard (RAW,
> MEDIUMRAW, XLATE, and UNICODE) buffer key events in the current vt's
> tty input. As recent Xorg releases no longer read input from the vt
> there are two problems:
> 
> 1) The tty input buffer eventually overflows because nothing is
> reading it, triggering an infinite flush_to_ldisc() kworker loop.
> 2) If the vt's mode isn't changed to RAW or MEDIUMRAW, key events
> remain translated by the kernel, causing shenanigans like pressing
> Ctrl+C in Xterm would send SIGTERM to the X server.

Seems very sane. Of course it all depends what a patch looks like...
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC] New console keyboard mode OFF
  2011-01-11 14:34 ` Pavel Machek
@ 2011-01-13 11:01   ` Arthur Taylor
  2011-01-23 13:00     ` Pavel Machek
  0 siblings, 1 reply; 4+ messages in thread
From: Arthur Taylor @ 2011-01-13 11:01 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-kernel

> Seems very sane. Of course it all depends what a patch looks like...
>                                                                        Pavel

Well the simple method is only 9 lines.

diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index e95d787..6dd3c68 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -654,7 +654,8 @@ static void k_spec(struct vc_data *vc, unsigned
char value, char up_flag)
 	if (value >= ARRAY_SIZE(fn_handler))
 		return;
 	if ((kbd->kbdmode == VC_RAW ||
-	     kbd->kbdmode == VC_MEDIUMRAW) &&
+	     kbd->kbdmode == VC_MEDIUMRAW ||
+	     kbd->kbdmode == VC_OFF) &&
 	     value != KVAL(K_SAK))
 		return;		/* SAK is allowed even in raw mode */
 	fn_handler[value](vc);
@@ -1295,7 +1296,7 @@ static void kbd_keycode(unsigned int keycode,
int down, int hw_raw)
 	if (rc == NOTIFY_STOP)
 		return;

-	if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
+	if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type
!= KT_SHIFT)
 		return;

 	(*k_handler[type])(vc, keysym & 0xff, !down);
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 6b68a0f..b498b2e 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -688,6 +688,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
 			kbd->kbdmode = VC_UNICODE;
 			compute_shiftstate();
 			break;
+		  case K_OFF:
+			kbd->kbdmode = VC_OFF;
+			break;
 		  default:
 			ret = -EINVAL;
 			goto out;
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index 506ad20..4b0761c 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -50,11 +50,12 @@ struct kbd_struct {
 #define VC_CAPSLOCK	2	/* capslock mode */
 #define VC_KANALOCK	3	/* kanalock mode */

-	unsigned char kbdmode:2;	/* one 2-bit value */
+	unsigned char kbdmode:3;	/* one 3-bit value */
 #define VC_XLATE	0	/* translate keycodes using keymap */
 #define VC_MEDIUMRAW	1	/* medium raw (keycode) mode */
 #define VC_RAW		2	/* raw (scancode) mode */
 #define VC_UNICODE	3	/* Unicode mode */
+#define VC_OFF		4	/* disabled mode */

 	unsigned char modeflags:5;
 #define VC_APPLIC	0	/* application key mode */
diff --git a/include/linux/kd.h b/include/linux/kd.h
index 15f2853..c36d847 100644
--- a/include/linux/kd.h
+++ b/include/linux/kd.h
@@ -81,6 +81,7 @@ struct unimapinit {
 #define		K_XLATE		0x01
 #define		K_MEDIUMRAW	0x02
 #define		K_UNICODE	0x03
+#define		K_OFF		0x04
 #define KDGKBMODE	0x4B44	/* gets current keyboard mode */
 #define KDSKBMODE	0x4B45	/* sets current keyboard mode */

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RFC] New console keyboard mode OFF
  2011-01-13 11:01   ` Arthur Taylor
@ 2011-01-23 13:00     ` Pavel Machek
  0 siblings, 0 replies; 4+ messages in thread
From: Pavel Machek @ 2011-01-23 13:00 UTC (permalink / raw)
  To: Arthur Taylor; +Cc: linux-kernel

On Thu 2011-01-13 03:01:48, Arthur Taylor wrote:
> > Seems very sane. Of course it all depends what a patch looks like...
> >                                                                        Pavel
> 
> Well the simple method is only 9 lines.

Cool. I guess you want to sign it off, and send it with
gregkh/akpm/alan cc-ed....

							Pavel

> diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
> index e95d787..6dd3c68 100644
> --- a/drivers/tty/vt/keyboard.c
> +++ b/drivers/tty/vt/keyboard.c
> @@ -654,7 +654,8 @@ static void k_spec(struct vc_data *vc, unsigned
> char value, char up_flag)
>  	if (value >= ARRAY_SIZE(fn_handler))
>  		return;
>  	if ((kbd->kbdmode == VC_RAW ||
> -	     kbd->kbdmode == VC_MEDIUMRAW) &&
> +	     kbd->kbdmode == VC_MEDIUMRAW ||
> +	     kbd->kbdmode == VC_OFF) &&
>  	     value != KVAL(K_SAK))
>  		return;		/* SAK is allowed even in raw mode */
>  	fn_handler[value](vc);
> @@ -1295,7 +1296,7 @@ static void kbd_keycode(unsigned int keycode,
> int down, int hw_raw)
>  	if (rc == NOTIFY_STOP)
>  		return;
> 
> -	if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
> +	if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type
> != KT_SHIFT)
>  		return;
> 
>  	(*k_handler[type])(vc, keysym & 0xff, !down);
> diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
> index 6b68a0f..b498b2e 100644
> --- a/drivers/tty/vt/vt_ioctl.c
> +++ b/drivers/tty/vt/vt_ioctl.c
> @@ -688,6 +688,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
>  			kbd->kbdmode = VC_UNICODE;
>  			compute_shiftstate();
>  			break;
> +		  case K_OFF:
> +			kbd->kbdmode = VC_OFF;
> +			break;
>  		  default:
>  			ret = -EINVAL;
>  			goto out;
> diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
> index 506ad20..4b0761c 100644
> --- a/include/linux/kbd_kern.h
> +++ b/include/linux/kbd_kern.h
> @@ -50,11 +50,12 @@ struct kbd_struct {
>  #define VC_CAPSLOCK	2	/* capslock mode */
>  #define VC_KANALOCK	3	/* kanalock mode */
> 
> -	unsigned char kbdmode:2;	/* one 2-bit value */
> +	unsigned char kbdmode:3;	/* one 3-bit value */
>  #define VC_XLATE	0	/* translate keycodes using keymap */
>  #define VC_MEDIUMRAW	1	/* medium raw (keycode) mode */
>  #define VC_RAW		2	/* raw (scancode) mode */
>  #define VC_UNICODE	3	/* Unicode mode */
> +#define VC_OFF		4	/* disabled mode */
> 
>  	unsigned char modeflags:5;
>  #define VC_APPLIC	0	/* application key mode */
> diff --git a/include/linux/kd.h b/include/linux/kd.h
> index 15f2853..c36d847 100644
> --- a/include/linux/kd.h
> +++ b/include/linux/kd.h
> @@ -81,6 +81,7 @@ struct unimapinit {
>  #define		K_XLATE		0x01
>  #define		K_MEDIUMRAW	0x02
>  #define		K_UNICODE	0x03
> +#define		K_OFF		0x04
>  #define KDGKBMODE	0x4B44	/* gets current keyboard mode */
>  #define KDSKBMODE	0x4B45	/* sets current keyboard mode */

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-01-23 13:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-09  9:00 [RFC] New console keyboard mode OFF Arthur Taylor
2011-01-11 14:34 ` Pavel Machek
2011-01-13 11:01   ` Arthur Taylor
2011-01-23 13:00     ` Pavel Machek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).