Discussion:
"i8042.c: No controller found" -> OS sees no keyboard if I type "in BIOS"
Tomasz Chmielewski
2009-05-14 13:57:01 UTC
Permalink
When I boot the guest and type (just hit any keys) in the VNC window
before the operating system boots, sometimes, the system loads with no
keyboard present - as signified in dmesg on guest:


i8042.c: No controller found

As a result, I can't use the keyboard in the VNC window.

If I start qemu process and I don't press any key, I can use the
keyboard once the operating system boots.


Rebooting the guest doesn't fix the problem, even if I don't touch the
keyboard before the OS boots any more.
Only stopping the guest and starting a new qemu process fixes the problem.


Anyone else saw it as well? If not, try something like that on your guests:


grep i8042 /var/log/kern*

(or grep "i8042.c: No controller found" /var/log/kern*)


Some more confirmations of this problem in the internet:


http://qemu-forum.ipi.fi/viewtopic.php?f=5&t=4461

http://osdir.com/ml/fedora-virt/2009-04/msg00066.html

http://www.proxmox.com/forum/showthread.php?t=1163
--
Tomasz Chmielewski
http://wpkg.org
Tomasz Chmielewski
2009-05-20 09:30:44 UTC
Permalink
Post by Tomasz Chmielewski
When I boot the guest and type (just hit any keys) in the VNC window
before the operating system boots, sometimes, the system loads with no
i8042.c: No controller found
As a result, I can't use the keyboard in the VNC window.
If I start qemu process and I don't press any key, I can use the
keyboard once the operating system boots.
Rebooting the guest doesn't fix the problem, even if I don't touch the
keyboard before the OS boots any more.
Only stopping the guest and starting a new qemu process fixes the problem.
grep i8042 /var/log/kern*
(or grep "i8042.c: No controller found" /var/log/kern*)
http://qemu-forum.ipi.fi/viewtopic.php?f=5&t=4461
http://osdir.com/ml/fedora-virt/2009-04/msg00066.html
http://www.proxmox.com/forum/showthread.php?t=1163
drivers/input/serio/i8042.c in the Linux kerne has this:

static int i8042_controller_check(void)
{
if (i8042_flush() == I8042_BUFFER_SIZE) {
printk(KERN_ERR "i8042.c: No controller found.\n");
return -ENODEV;
}

return 0;
}


So, can it be that if we type anything on keyboard (or move mouse) while
Qemu's BIOS is still booting or later in the bootloader (GRUB, lilo),
some buffer is not flushed and Linux gets confused? And as a result,
decides there is no keyboard?
--
Tomasz Chmielewski
http://wpkg.org
Tomasz Chmielewski
2009-05-20 13:30:09 UTC
Permalink
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
When I boot the guest and type (just hit any keys) in the VNC window
before the operating system boots, sometimes, the system loads with no
i8042.c: No controller found
As a result, I can't use the keyboard in the VNC window.
static int i8042_controller_check(void)
{
if (i8042_flush() == I8042_BUFFER_SIZE) {
printk(KERN_ERR "i8042.c: No controller found.\n");
return -ENODEV;
}
return 0;
}
So, can it be that if we type anything on keyboard (or move mouse) while
Qemu's BIOS is still booting or later in the bootloader (GRUB, lilo),
some buffer is not flushed and Linux gets confused? And as a result,
decides there is no keyboard?
Yes, this is what seems to happen - Qemu's keyboard buffer seems to be infinite
or at least very big; normal 8042 devices have buffer of 16 bytes only.

If we add "i8042.debug" parameter to kernel command line,
we will see how many characters were flushed during boot, i.e.:


drivers/input/serio/i8042.c: ff <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 18 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 92 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 00 <- i8042 (flush, aux) [0]
(...)


With this 16 byte buffer in drivers/input/serio/i8042.h (before 2.6.11 it was
32 bytes I think):

#define I8042_BUFFER_SIZE 16


and this piece of code in drivers/input/serio/i8042.c:


/*
* i8042_flush() flushes all data that may be in the keyboard and mouse buffers
* of the i8042 down the toilet.
*/

static int i8042_flush(void)
{
unsigned long flags;
unsigned char data, str;
int i = 0;

spin_lock_irqsave(&i8042_lock, flags);

while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) {
udelay(50);
data = i8042_read_data();
i++;
dbg("%02x <- i8042 (flush, %s)", data,
str & I8042_STR_AUXDATA ? "aux" : "kbd");
}

spin_unlock_irqrestore(&i8042_lock, flags);

return i;
}



Linux kernel thinks there is no controller:


(...)
drivers/input/serio/i8042.c: 28 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 00 <- i8042 (flush, aux) [0]
i8042.c: No controller found.


If we increase "I8042_BUFFER_SIZE" to 256 or more, we have a much better chance
that a booted Linux will have a keyboard present.

So, who's to be blamed?

Linux kernel for having its i8042 buffer to small (16 bytes), fixable with:


--- i8042.h.orig 2009-05-20 15:26:32.000000000 +0200
+++ i8042.h 2009-05-20 15:26:32.000000000 +0200
@@ -73,7 +73,7 @@
* the i8042 buffers.
*/

-#define I8042_BUFFER_SIZE 16
+#define I8042_BUFFER_SIZE 256

/*
* Number of AUX ports on controllers supporting active multiplexing



Or Qemu, for having its keyboard buffer too large (I'm not sure, but probably 256 bytes)?
--
Tomasz Chmielewski
http://wpkg.org
Marcelo Tosatti
2009-06-07 04:04:10 UTC
Permalink
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
When I boot the guest and type (just hit any keys) in the VNC window
before the operating system boots, sometimes, the system loads with
i8042.c: No controller found
As a result, I can't use the keyboard in the VNC window.
static int i8042_controller_check(void)
{
if (i8042_flush() == I8042_BUFFER_SIZE) {
printk(KERN_ERR "i8042.c: No controller found.\n");
return -ENODEV;
}
return 0;
}
So, can it be that if we type anything on keyboard (or move mouse)
while Qemu's BIOS is still booting or later in the bootloader (GRUB,
lilo), some buffer is not flushed and Linux gets confused? And as a
result, decides there is no keyboard?
Yes, this is what seems to happen - Qemu's keyboard buffer seems to be infinite
or at least very big; normal 8042 devices have buffer of 16 bytes only.
If we add "i8042.debug" parameter to kernel command line,
drivers/input/serio/i8042.c: ff <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 18 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 92 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 00 <- i8042 (flush, aux) [0]
(...)
With this 16 byte buffer in drivers/input/serio/i8042.h (before 2.6.11 it was
#define I8042_BUFFER_SIZE 16
/*
* i8042_flush() flushes all data that may be in the keyboard and mouse buffers
* of the i8042 down the toilet.
*/
static int i8042_flush(void)
{
unsigned long flags;
unsigned char data, str;
int i = 0;
spin_lock_irqsave(&i8042_lock, flags);
while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) {
udelay(50);
data = i8042_read_data();
i++;
dbg("%02x <- i8042 (flush, %s)", data,
str & I8042_STR_AUXDATA ? "aux" : "kbd");
}
spin_unlock_irqrestore(&i8042_lock, flags);
return i;
}
(...)
drivers/input/serio/i8042.c: 28 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 00 <- i8042 (flush, aux) [0]
i8042.c: No controller found.
If we increase "I8042_BUFFER_SIZE" to 256 or more, we have a much better
chance that a booted Linux will have a keyboard present.
So, who's to be blamed?
--- i8042.h.orig 2009-05-20 15:26:32.000000000 +0200
+++ i8042.h 2009-05-20 15:26:32.000000000 +0200
@@ -73,7 +73,7 @@
* the i8042 buffers.
*/
-#define I8042_BUFFER_SIZE 16
+#define I8042_BUFFER_SIZE 256
/*
* Number of AUX ports on controllers supporting active multiplexing
Or Qemu, for having its keyboard buffer too large (I'm not sure, but probably 256 bytes)?
All references (*) i could find mention 16 bytes of output buffer
(including the Linux source as you mentioned, which was reduced from 32
to 16 somewhere in the 2.6.10 era).

http://www.computer-engineering.org/ps2protocol/

http://linux.bkbits.net:8080/linux-2.6.28-stable/drivers/input/serio/i8042.h?PAGE=diffs&REV=4203735dp_doSExYU6ido8KnczbjzQ

Reducing PS2_QUEUE_SIZE to 16 also makes the Linux detection loop happy.

If QEMU claims to emulate i8042, it should be similar to real hardware.

However i'm not familiar with PS/2 or i8042. Anthony?
Tomasz Chmielewski
2009-06-08 13:51:14 UTC
Permalink
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
Or Qemu, for having its keyboard buffer too large (I'm not sure, but probably 256 bytes)?
All references (*) i could find mention 16 bytes of output buffer
(including the Linux source as you mentioned, which was reduced from 32
to 16 somewhere in the 2.6.10 era).
http://www.computer-engineering.org/ps2protocol/
http://linux.bkbits.net:8080/linux-2.6.28-stable/drivers/input/serio/i8042.h?PAGE=diffs&REV=4203735dp_doSExYU6ido8KnczbjzQ
Reducing PS2_QUEUE_SIZE to 16 also makes the Linux detection loop happy.
If QEMU claims to emulate i8042, it should be similar to real hardware.
However i'm not familiar with PS/2 or i8042. Anthony?
This:

#define KBD_QUEUE_SIZE 256

dates back to qemu-0.5.1, where it was defined in vl.c.

Seems like it's in Qemu from the very beginning?


PS2_QUEUE_SIZE 256 was introduced in qemu-0.8.0.
--
Tomasz Chmielewski
http://wpkg.org
Tomasz Chmielewski
2009-06-08 14:13:09 UTC
Permalink
Post by Tomasz Chmielewski
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
Or Qemu, for having its keyboard buffer too large (I'm not sure, but
probably 256 bytes)?
All references (*) i could find mention 16 bytes of output buffer
(including the Linux source as you mentioned, which was reduced from 32
to 16 somewhere in the 2.6.10 era).
http://www.computer-engineering.org/ps2protocol/
http://linux.bkbits.net:8080/linux-2.6.28-stable/drivers/input/serio/i8042.h?PAGE=diffs&REV=4203735dp_doSExYU6ido8KnczbjzQ
Reducing PS2_QUEUE_SIZE to 16 also makes the Linux detection loop happy.
If QEMU claims to emulate i8042, it should be similar to real hardware.
However i'm not familiar with PS/2 or i8042. Anthony?
#define KBD_QUEUE_SIZE 256
dates back to qemu-0.5.1, where it was defined in vl.c.
Seems like it's in Qemu from the very beginning?
PS2_QUEUE_SIZE 256 was introduced in qemu-0.8.0.
BTW, with "PS2_QUEUE_SIZE 16" I'm still able to trigger:

i8042.c: No controller found.


Only with "PS2_QUEUE_SIZE 15" keyboard is detected every time I boot the
guest (unless that's what you meant by setting it to 16).
--
Tomasz Chmielewski
http://wpkg.org
Marcelo Tosatti
2009-06-08 14:30:21 UTC
Permalink
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
Or Qemu, for having its keyboard buffer too large (I'm not sure,
but probably 256 bytes)?
All references (*) i could find mention 16 bytes of output buffer
(including the Linux source as you mentioned, which was reduced from 32
to 16 somewhere in the 2.6.10 era).
http://www.computer-engineering.org/ps2protocol/
http://linux.bkbits.net:8080/linux-2.6.28-stable/drivers/input/serio/i8042.h?PAGE=diffs&REV=4203735dp_doSExYU6ido8KnczbjzQ
Reducing PS2_QUEUE_SIZE to 16 also makes the Linux detection loop happy.
If QEMU claims to emulate i8042, it should be similar to real hardware.
However i'm not familiar with PS/2 or i8042. Anthony?
#define KBD_QUEUE_SIZE 256
dates back to qemu-0.5.1, where it was defined in vl.c.
Seems like it's in Qemu from the very beginning?
PS2_QUEUE_SIZE 256 was introduced in qemu-0.8.0.
i8042.c: No controller found.
I was not able to trigger it by changing PS2_QUEUE_SIZE to 16 (which
shows the testing was lame, since you did trigger it).
Post by Tomasz Chmielewski
Only with "PS2_QUEUE_SIZE 15" keyboard is detected every time I boot the
guest (unless that's what you meant by setting it to 16).
No, 16. Maybe there's some off-by-one bug in hw/ps2.c? Also yesterday i
was not entirely sure the KBD_STAT_OBF (output buffer empty/full status
bit) handling was correct (thus the attached patch), but now a quick
look seems to indicate it is alright, since it be will update these bits
via:

ps2_read_data
->update_irq(s->update_arg, q->count != 0)
kbd_update_irq


diff --git a/hw/pckbd.c b/hw/pckbd.c
index 3ef3594..7d21994 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -181,6 +181,13 @@ static uint32_t kbd_read_status(void *opaque, uint32_t addr)
{
KBDState *s = opaque;
int val;
+
+ if (ps2_buffer_empty(s->kbd))
+ s->status &= ~KBD_STAT_OBF;
+
+ if (ps2_buffer_empty(s->mouse))
+ s->status &= ~KBD_STAT_MOUSE_OBF;
+
val = s->status;
#if defined(DEBUG_KBD)
printf("kbd: read status=0x%02x\n", val);
diff --git a/hw/ps2.c b/hw/ps2.c
index b1352d0..0f9bd67 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -70,7 +70,7 @@
#define MOUSE_STATUS_ENABLED 0x20
#define MOUSE_STATUS_SCALE21 0x10

-#define PS2_QUEUE_SIZE 256
+#define PS2_QUEUE_SIZE 16

typedef struct {
uint8_t data[PS2_QUEUE_SIZE];
@@ -181,6 +181,15 @@ uint32_t ps2_read_data(void *opaque)
return val;
}

+int ps2_buffer_empty(void *opaque)
+{
+ PS2State *s = (PS2State *)opaque;
+ PS2Queue *q;
+
+ q = &s->queue;
+ return (q->count == 0);
+}
+
static void ps2_reset_keyboard(PS2KbdState *s)
{
s->scan_enabled = 1;
diff --git a/hw/ps2.h b/hw/ps2.h
index 32a4231..af76c92 100644
--- a/hw/ps2.h
+++ b/hw/ps2.h
@@ -4,6 +4,7 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg);
void ps2_write_mouse(void *, int val);
void ps2_write_keyboard(void *, int val);
uint32_t ps2_read_data(void *);
+int ps2_buffer_empty(void *);
void ps2_queue(void *, int b);
void ps2_keyboard_set_translation(void *opaque, int mode);
void ps2_mouse_fake_event(void *opaque);
Tomasz Chmielewski
2009-06-08 15:11:18 UTC
Permalink
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
PS2_QUEUE_SIZE 256 was introduced in qemu-0.8.0.
i8042.c: No controller found.
I was not able to trigger it by changing PS2_QUEUE_SIZE to 16 (which
shows the testing was lame, since you did trigger it).
For me, moving mouse adds to the buffer really fast.
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
Only with "PS2_QUEUE_SIZE 15" keyboard is detected every time I boot the
guest (unless that's what you meant by setting it to 16).
No, 16. Maybe there's some off-by-one bug in hw/ps2.c? Also yesterday i
was not entirely sure the KBD_STAT_OBF (output buffer empty/full status
bit) handling was correct (thus the attached patch), but now a quick
look seems to indicate it is alright, since it be will update these bits
(...)
Post by Marcelo Tosatti
-#define PS2_QUEUE_SIZE 256
+#define PS2_QUEUE_SIZE 16
15? With 16 it can still break (broken BIOS?).
--
Tomasz Chmielewski
http://wpkg.org
Mark Cave-Ayland
2009-06-08 15:48:01 UTC
Permalink
Post by Tomasz Chmielewski
Post by Marcelo Tosatti
No, 16. Maybe there's some off-by-one bug in hw/ps2.c? Also yesterday i
was not entirely sure the KBD_STAT_OBF (output buffer empty/full status
bit) handling was correct (thus the attached patch), but now a quick
look seems to indicate it is alright, since it be will update these bits
(...)
Post by Marcelo Tosatti
-#define PS2_QUEUE_SIZE 256
+#define PS2_QUEUE_SIZE 16
15? With 16 it can still break (broken BIOS?).
FWIW I wonder if this is also responsible for the bug report I posted here:

http://lists.gnu.org/archive/html/qemu-devel/2008-05/msg00853.html

Basically after a random length of time from 1 - 5 days, the mouse under
an NT4 guest goes crazy - a single touch and it goes flying randomly all
around the screen. Restarting the VM resolves the issue.


ATB,

Mark.
--
Mark Cave-Ayland - Senior Technical Architect
PostgreSQL - PostGIS
Sirius Corporation plc - control through freedom
http://www.siriusit.co.uk
t: +44 870 608 0063
Mark Cave-Ayland
2009-06-23 12:27:35 UTC
Permalink
Post by Mark Cave-Ayland
Post by Tomasz Chmielewski
Post by Marcelo Tosatti
-#define PS2_QUEUE_SIZE 256
+#define PS2_QUEUE_SIZE 16
15? With 16 it can still break (broken BIOS?).
http://lists.gnu.org/archive/html/qemu-devel/2008-05/msg00853.html
Basically after a random length of time from 1 - 5 days, the mouse under
an NT4 guest goes crazy - a single touch and it goes flying randomly all
around the screen. Restarting the VM resolves the issue.
Sorry for resurrecting an old thread again, but thought it may be useful
for the archives. I upgraded to kvm-86 and changed PS2_QUEUE_SIZE to 16
for my troublesome NT4 guest, and when it fired up, the keyboard worked
fine but the mouse would not respond.

I then tried raising PS2_QUEUE_SIZE to 32 and then both the mouse and
keyboard started to work. I'll keep an eye on this and see whether it
starts to behave strangely again with this smaller buffer size.


HTH,

Mark.
--
Mark Cave-Ayland - Senior Technical Architect
PostgreSQL - PostGIS
Sirius Corporation plc - control through freedom
http://www.siriusit.co.uk
t: +44 870 608 0063
Avi Kivity
2009-06-08 14:59:15 UTC
Permalink
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
Or Qemu, for having its keyboard buffer too large (I'm not sure,
but probably 256 bytes)?
All references (*) i could find mention 16 bytes of output buffer
(including the Linux source as you mentioned, which was reduced from 32
to 16 somewhere in the 2.6.10 era).
http://www.computer-engineering.org/ps2protocol/
http://linux.bkbits.net:8080/linux-2.6.28-stable/drivers/input/serio/i8042.h?PAGE=diffs&REV=4203735dp_doSExYU6ido8KnczbjzQ
Reducing PS2_QUEUE_SIZE to 16 also makes the Linux detection loop happy.
If QEMU claims to emulate i8042, it should be similar to real hardware.
However i'm not familiar with PS/2 or i8042. Anthony?
#define KBD_QUEUE_SIZE 256
dates back to qemu-0.5.1, where it was defined in vl.c.
Seems like it's in Qemu from the very beginning?
PS2_QUEUE_SIZE 256 was introduced in qemu-0.8.0.
i8042.c: No controller found.
Only with "PS2_QUEUE_SIZE 15" keyboard is detected every time I boot
the guest (unless that's what you meant by setting it to 16).
I think this points to a bug in the bios. The keyboard-internal queue
size shouldn't cause any problems.
--
error compiling committee.c: too many arguments to function
Tomasz Chmielewski
2009-06-08 15:08:35 UTC
Permalink
Post by Avi Kivity
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
PS2_QUEUE_SIZE 256 was introduced in qemu-0.8.0.
i8042.c: No controller found.
Only with "PS2_QUEUE_SIZE 15" keyboard is detected every time I boot
the guest (unless that's what you meant by setting it to 16).
I think this points to a bug in the bios. The keyboard-internal queue
size shouldn't cause any problems.
It could be.

That's something along the lines with what Vojtech Pavlik suggested[1]:

This looks seriously like uninitialized memory (12-bit FAT
perhaps?) - and very much like a Qemu bug. It doesn't even make
sense if interpreted as keyboard scancodes - 00 is reserved and ff
is an error condition.

[1] http://lists.gnu.org/archive/html/qemu-devel/2009-05/msg00943.html
--
Tomasz Chmielewski
http://wpkg.org
Paul Brook
2009-06-08 15:28:30 UTC
Permalink
Post by Avi Kivity
Post by Tomasz Chmielewski
i8042.c: No controller found.
Only with "PS2_QUEUE_SIZE 15" keyboard is detected every time I boot
the guest (unless that's what you meant by setting it to 16).
I think this points to a bug in the bios. The keyboard-internal queue
size shouldn't cause any problems.
Either way, you're just papering over bugs in the bios/kernel.
My guess is that the bios is assuming it can drain the queue faster than
external events can fill it back up. On real hardware this is often true (CPU
and system bus speeds are many orders of magnitude greater than the keyboard
serial line). However in a non cycle accurate simulator (like qemu) the
keyboard events can happen infinitely fast. i.e. even with an internal queue
size of 1 the bug will still trigger if sufficiently many PS2 events occur
while the guest is draining the queue.

Paul
Dinesh Subhraveti
2009-07-08 21:08:24 UTC
Permalink
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
When I boot the guest and type (just hit any keys) in the VNC window
before the operating system boots, sometimes, the system loads with
i8042.c: No controller found
As a result, I can't use the keyboard in the VNC window.
static int i8042_controller_check(void)
{
if (i8042_flush() == I8042_BUFFER_SIZE) {
printk(KERN_ERR "i8042.c: No controller found.\n");
return -ENODEV;
}
return 0;
}
So, can it be that if we type anything on keyboard (or move mouse)
while Qemu's BIOS is still booting or later in the bootloader (GRUB,
lilo), some buffer is not flushed and Linux gets confused? And as a
result, decides there is no keyboard?
Yes, this is what seems to happen - Qemu's keyboard buffer seems to be infinite
or at least very big; normal 8042 devices have buffer of 16 bytes only.
If we add "i8042.debug" parameter to kernel command line,
drivers/input/serio/i8042.c: ff <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 18 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 92 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 00 <- i8042 (flush, aux) [0]
(...)
With this 16 byte buffer in drivers/input/serio/i8042.h (before 2.6.11 it was
#define I8042_BUFFER_SIZE 16
/*
* i8042_flush() flushes all data that may be in the keyboard and mouse buffers
* of the i8042 down the toilet.
*/
static int i8042_flush(void)
{
unsigned long flags;
unsigned char data, str;
int i = 0;
spin_lock_irqsave(&i8042_lock, flags);
while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) {
udelay(50);
data = i8042_read_data();
i++;
dbg("%02x <- i8042 (flush, %s)", data,
str & I8042_STR_AUXDATA ? "aux" : "kbd");
}
spin_unlock_irqrestore(&i8042_lock, flags);
return i;
}
(...)
drivers/input/serio/i8042.c: 28 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 00 <- i8042 (flush, aux) [0]
i8042.c: No controller found.
If we increase "I8042_BUFFER_SIZE" to 256 or more, we have a much better
chance that a booted Linux will have a keyboard present.
So, who's to be blamed?
--- i8042.h.orig 2009-05-20 15:26:32.000000000 +0200
+++ i8042.h 2009-05-20 15:26:32.000000000 +0200
@@ -73,7 +73,7 @@
* the i8042 buffers.
*/
-#define I8042_BUFFER_SIZE 16
+#define I8042_BUFFER_SIZE 256
/*
* Number of AUX ports on controllers supporting active multiplexing
Or Qemu, for having its keyboard buffer too large (I'm not sure, but probably 256 bytes)?
All references (*) i could find mention 16 bytes of output buffer
(including the Linux source as you mentioned, which was reduced from 32
to 16 somewhere in the 2.6.10 era).
http://www.computer-engineering.org/ps2protocol/
http://linux.bkbits.net:8080/linux-2.6.28-stable/drivers/input/serio/i8042.h?
PAGE=diffs&REV=4203735dp_doSExYU6ido8KnczbjzQ
Post by Marcelo Tosatti
Reducing PS2_QUEUE_SIZE to 16 also makes the Linux detection loop happy.
If QEMU claims to emulate i8042, it should be similar to real hardware.
Some new findings on this old issue:

Reducing PS2_QUEUE_SIZE to 16 prevents the PS2 mouse event handler
(ps2_mouse_event()) from queuing any mouse events. It checks if there is at
least 16 bytes of space left in the queue, if not, the event is dropped.

The side effect of this is that, the buffer will not become full, and
i8042_controller_check() in guest Linux is happy and keyboard works normally
after reboot. However, mouse remains inactive throughout, because its events
are always dropped.

Two questions:

- Does it make sense to reduce the size of reserved space (currently 16 bytes)
checked by ps2_mouse_event()? It will probably break other things since the
reserved space is tied to the length of mouse movement. If the distance moved
can fit in 1 byte (+/- 128), it is queued as 1 event. For longer distances,
it is queued as multiple events requiring more buffer space. 16 bytes is
probably a conservative estimate of the longest distance moved.

- Why does the guest kernel (i8042_controller_check()) conclude that there is
no i8042 controller if it finds the queue to be full? Reducing PS2_QUEUE_SIZE
to 16 is still not enough. It need to be something less than 16 for the
guest kernel to successfully detect the controller.

Interesetingly, the problem is not seen on RHEL 5.3. It leaves the mouse
disabled on shutdown via AUX_DISABLE_DEV mouse command. AUX_DISABLE_DEV
command resets MOUSE_STATUS_ENABLED flag in PS2MouseState->mouse_status, which
makes mouse
events to be dropped by ps2_mouse_event().

On SLES 11, however, mouse is disabled first but then it is again re-enabled
(via AUX_ENABLE_DEV) prior to resetting the processor, leaving the mouse
enabled during BIOS. Not clear what makes the guest re-enable the mouse on
shutdown.

Folks have some clues on the right way to address this?

Dinesh Subhraveti
Dinesh Subhraveti
2009-07-09 01:07:27 UTC
Permalink
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
When I boot the guest and type (just hit any keys) in the VNC window
before the operating system boots, sometimes, the system loads with
i8042.c: No controller found
As a result, I can't use the keyboard in the VNC window.
static int i8042_controller_check(void)
{
if (i8042_flush() == I8042_BUFFER_SIZE) {
printk(KERN_ERR "i8042.c: No controller found.\n");
return -ENODEV;
}
return 0;
}
So, can it be that if we type anything on keyboard (or move mouse)
while Qemu's BIOS is still booting or later in the bootloader (GRUB,
lilo), some buffer is not flushed and Linux gets confused? And as a
result, decides there is no keyboard?
Yes, this is what seems to happen - Qemu's keyboard buffer seems to be infinite
or at least very big; normal 8042 devices have buffer of 16 bytes only.
If we add "i8042.debug" parameter to kernel command line,
drivers/input/serio/i8042.c: ff <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 18 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 92 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 00 <- i8042 (flush, aux) [0]
(...)
With this 16 byte buffer in drivers/input/serio/i8042.h (before 2.6.11 it was
#define I8042_BUFFER_SIZE 16
/*
* i8042_flush() flushes all data that may be in the keyboard and mouse buffers
* of the i8042 down the toilet.
*/
static int i8042_flush(void)
{
unsigned long flags;
unsigned char data, str;
int i = 0;
spin_lock_irqsave(&i8042_lock, flags);
while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) {
udelay(50);
data = i8042_read_data();
i++;
dbg("%02x <- i8042 (flush, %s)", data,
str & I8042_STR_AUXDATA ? "aux" : "kbd");
}
spin_unlock_irqrestore(&i8042_lock, flags);
return i;
}
(...)
drivers/input/serio/i8042.c: 28 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 00 <- i8042 (flush, aux) [0]
i8042.c: No controller found.
If we increase "I8042_BUFFER_SIZE" to 256 or more, we have a much better
chance that a booted Linux will have a keyboard present.
So, who's to be blamed?
--- i8042.h.orig 2009-05-20 15:26:32.000000000 +0200
+++ i8042.h 2009-05-20 15:26:32.000000000 +0200
@@ -73,7 +73,7 @@
* the i8042 buffers.
*/
-#define I8042_BUFFER_SIZE 16
+#define I8042_BUFFER_SIZE 256
/*
* Number of AUX ports on controllers supporting active multiplexing
Or Qemu, for having its keyboard buffer too large (I'm not sure, but probably 256 bytes)?
All references (*) i could find mention 16 bytes of output buffer
(including the Linux source as you mentioned, which was reduced from 32
to 16 somewhere in the 2.6.10 era).
http://www.computer-engineering.org/ps2protocol/
http://linux.bkbits.net:8080/linux-2.6.28-stable/drivers/input/serio/i8042.h?
PAGE=diffs&REV=4203735dp_doSExYU6ido8KnczbjzQ
Post by Marcelo Tosatti
Reducing PS2_QUEUE_SIZE to 16 also makes the Linux detection loop happy.
If QEMU claims to emulate i8042, it should be similar to real hardware.
Some new findings on this old thread:

Reducing PS2_QUEUE_SIZE to 16 prevents the PS2 mouse event handler
(ps2_mouse_event()) from queuing any mouse events. It checks if there is at
least 16 bytes of space left in the queue, if not, the event is dropped.

The side effect of this is that, the buffer will not become full, and
i8042_controller_check() in the guest passes the check and keyboard works
normally after reboot. However, mouse remains inactive throughout, because
its events are always dropped.

Two questions:

- Does it make sense to reduce the size of reserved space (currently 16 bytes)
checked by ps2_mouse_event()? It will probably break other things since the
size of reserved space is tied to the distance mouse is moved. If the
distance moved can fit in 1 byte (+/- 128), it is queued as one event. For
longer distances, it is queued as multiple events, requiring more buffer
space. 16 bytes is probably a conservative estimate of the longest distance
moved.

- Why does the guest kernel (i8042_controller_check()) conclude that there is
no i8042 controller if it finds the queue to be full? Reducing PS2_QUEUE_SIZE
to 16 is still not enough. It need to be something less than 16 for the guest
kernel to successfully detect the controller.

Interestingly, the problem is not seen on RHEL 5.3. It leaves the mouse
disabled on shutdown via AUX_DISABLE_DEV mouse command. AUX_DISABLE_DEV
command resets MOUSE_STATUS_ENABLED flag in PS2MouseState->mouse_status, which
makes mouse events to be dropped by ps2_mouse_event().

On SLES 11, however, mouse is disabled but then it is again re-enabled (via
AUX_ENABLE_DEV) prior to resetting the processor, which leaves the mouse
enabled during BIOS. Not clear what makes the guest re-enable the mouse on
shutdown.

Folks have some clues on the right way to address this?

Dinesh Subhraveti
Dinesh Subhraveti
2009-07-09 20:52:09 UTC
Permalink
Post by Tomasz Chmielewski
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
Post by Tomasz Chmielewski
When I boot the guest and type (just hit any keys) in the VNC window
before the operating system boots, sometimes, the system loads with
i8042.c: No controller found
As a result, I can't use the keyboard in the VNC window.
static int i8042_controller_check(void)
{
if (i8042_flush() == I8042_BUFFER_SIZE) {
printk(KERN_ERR "i8042.c: No controller found.\n");
return -ENODEV;
}
return 0;
}
So, can it be that if we type anything on keyboard (or move mouse)
while Qemu's BIOS is still booting or later in the bootloader (GRUB,
lilo), some buffer is not flushed and Linux gets confused? And as a
result, decides there is no keyboard?
Yes, this is what seems to happen - Qemu's keyboard buffer seems to be
infinite
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
or at least very big; normal 8042 devices have buffer of 16 bytes only.
If we add "i8042.debug" parameter to kernel command line,
drivers/input/serio/i8042.c: ff <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 18 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 92 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 00 <- i8042 (flush, aux) [0]
(...)
With this 16 byte buffer in drivers/input/serio/i8042.h (before 2.6.11
it
was
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
#define I8042_BUFFER_SIZE 16
/*
* i8042_flush() flushes all data that may be in the keyboard and mouse
buffers
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
* of the i8042 down the toilet.
*/
static int i8042_flush(void)
{
unsigned long flags;
unsigned char data, str;
int i = 0;
spin_lock_irqsave(&i8042_lock, flags);
while (((str = i8042_read_status()) & I8042_STR_OBF) && (i <
I8042_BUFFER_SIZE)) {
Post by Marcelo Tosatti
Post by Tomasz Chmielewski
udelay(50);
data = i8042_read_data();
i++;
dbg("%02x <- i8042 (flush, %s)", data,
str & I8042_STR_AUXDATA ? "aux" : "kbd");
}
spin_unlock_irqrestore(&i8042_lock, flags);
return i;
}
(...)
drivers/input/serio/i8042.c: 28 <- i8042 (flush, aux) [0]
drivers/input/serio/i8042.c: 00 <- i8042 (flush, aux) [0]
i8042.c: No controller found.
If we increase "I8042_BUFFER_SIZE" to 256 or more, we have a much better
chance that a booted Linux will have a keyboard present.
So, who's to be blamed?
--- i8042.h.orig 2009-05-20 15:26:32.000000000 +0200
+++ i8042.h 2009-05-20 15:26:32.000000000 +0200
@@ -73,7 +73,7 @@
* the i8042 buffers.
*/
-#define I8042_BUFFER_SIZE 16
+#define I8042_BUFFER_SIZE 256
/*
* Number of AUX ports on controllers supporting active multiplexing
Or Qemu, for having its keyboard buffer too large (I'm not sure, but
probably 256 bytes)?
Post by Marcelo Tosatti
All references (*) i could find mention 16 bytes of output buffer
(including the Linux source as you mentioned, which was reduced from 32
to 16 somewhere in the 2.6.10 era).
http://www.computer-engineering.org/ps2protocol/
http://linux.bkbits.net:8080/linux-2.6.28-stable/drivers/input/serio/i8042.h?
PAGE=diffs&REV=4203735dp_doSExYU6ido8KnczbjzQ
Post by Marcelo Tosatti
Reducing PS2_QUEUE_SIZE to 16 also makes the Linux detection loop happy.
If QEMU claims to emulate i8042, it should be similar to real hardware.
Reducing PS2_QUEUE_SIZE to 16 prevents the PS2 mouse event handler
(ps2_mouse_event()) from queuing any mouse events. It checks if there is at
least 16 bytes of space left in the queue, if not, the event is dropped.
The side effect of this is that, the buffer will not become full, and
i8042_controller_check() in the guest passes the check and keyboard works
normally after reboot. However, mouse remains inactive throughout, because
its events are always dropped.
- Does it make sense to reduce the size of reserved space (currently 16 bytes)
checked by ps2_mouse_event()? It will probably break other things since the
size of reserved space is tied to the distance mouse is moved. If the
distance moved can fit in 1 byte (+/- 128), it is queued as one event.
For
longer distances, it is queued as multiple events, requiring more buffer
space. 16 bytes is probably a conservative estimate of the longest distance
moved.
- Why does the guest kernel (i8042_controller_check()) conclude that there is
no i8042 controller if it finds the queue to be full? Reducing PS2_QUEUE_SIZE
to 16 is still not enough. It need to be something less than 16 for the guest
kernel to successfully detect the controller.
Interestingly, the problem is not seen on RHEL 5.3. It leaves the mouse
disabled on shutdown via AUX_DISABLE_DEV mouse command. AUX_DISABLE_DEV
command resets MOUSE_STATUS_ENABLED flag in PS2MouseState->mouse_status, which
makes mouse events to be dropped by ps2_mouse_event().
On SLES 11, however, mouse is disabled but then it is again re-enabled (via
AUX_ENABLE_DEV) prior to resetting the processor, which leaves the mouse
enabled during BIOS. Not clear what makes the guest re-enable the mouse on
shutdown.
Folks have some clues on the right way to address this?
Sorry for the duplicate message above (mail server was taking hours to post,
and I got impatient...)

Changing PS2_QUEUE_SIZE to 15 and the "reserved space" to 8 fixes the
problem for me:

diff --git a/hw/ps2.c b/hw/ps2.c
index fb77005..51a3ab8 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -70,7 +70,7 @@
#define MOUSE_STATUS_ENABLED 0x20
#define MOUSE_STATUS_SCALE21 0x10

-#define PS2_QUEUE_SIZE 256
+#define PS2_QUEUE_SIZE 15

typedef struct {
uint8_t data[PS2_QUEUE_SIZE];
@@ -346,7 +346,7 @@ static void ps2_mouse_event(void *opaque,
s->mouse_buttons = buttons_state;

if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
- (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
+ (s->common.queue.count < (PS2_QUEUE_SIZE - 8))) {
for(;;) {
/* if not remote, send event. Multiple events are sent if
too big deltas */

Both keyboard and mouse remain responsive after reboot, no matter how much I
type / move the mouse during reboot.

Any comments?

Thanks,
Dinesh Subhraveti
Mark Cave-Ayland
2009-07-10 08:21:17 UTC
Permalink
Post by Dinesh Subhraveti
Sorry for the duplicate message above (mail server was taking hours to post,
and I got impatient...)
Changing PS2_QUEUE_SIZE to 15 and the "reserved space" to 8 fixes the
diff --git a/hw/ps2.c b/hw/ps2.c
index fb77005..51a3ab8 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -70,7 +70,7 @@
#define MOUSE_STATUS_ENABLED 0x20
#define MOUSE_STATUS_SCALE21 0x10
-#define PS2_QUEUE_SIZE 256
+#define PS2_QUEUE_SIZE 15
typedef struct {
uint8_t data[PS2_QUEUE_SIZE];
@@ -346,7 +346,7 @@ static void ps2_mouse_event(void *opaque,
s->mouse_buttons = buttons_state;
if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
- (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
+ (s->common.queue.count < (PS2_QUEUE_SIZE - 8))) {
for(;;) {
/* if not remote, send event. Multiple events are sent if
too big deltas */
Both keyboard and mouse remain responsive after reboot, no matter how much I
type / move the mouse during reboot.
Any comments?
Hi Dinesh,

Thanks for this. I've applied this patch to the copy of kvm which hosts
our NT4 virtual which has been experiencing random mouse/keyboard input
problems. Fingers crossed that your patch will fix this issue for good...


ATB,

Mark.
--
Mark Cave-Ayland - Senior Technical Architect
PostgreSQL - PostGIS
Sirius Corporation plc - control through freedom
http://www.siriusit.co.uk
t: +44 870 608 0063
Dinesh Subhraveti
2009-07-10 21:45:43 UTC
Permalink
Post by Mark Cave-Ayland
Post by Dinesh Subhraveti
Sorry for the duplicate message above (mail server was taking hours to
post, and I got impatient...)
Changing PS2_QUEUE_SIZE to 15 and the "reserved space" to 8 fixes the
diff --git a/hw/ps2.c b/hw/ps2.c
index fb77005..51a3ab8 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -70,7 +70,7 @@
#define MOUSE_STATUS_ENABLED 0x20
#define MOUSE_STATUS_SCALE21 0x10
-#define PS2_QUEUE_SIZE 256
+#define PS2_QUEUE_SIZE 15
typedef struct {
uint8_t data[PS2_QUEUE_SIZE];
@@ -346,7 +346,7 @@ static void ps2_mouse_event(void *opaque,
s->mouse_buttons = buttons_state;
if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
- (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
+ (s->common.queue.count < (PS2_QUEUE_SIZE - 8))) {
for(;;) {
/* if not remote, send event. Multiple events are sent if
too big deltas */
Both keyboard and mouse remain responsive after reboot, no matter how
much I type / move the mouse during reboot.
Any comments?
Hi Dinesh,
Thanks for this. I've applied this patch to the copy of kvm which hosts
our NT4 virtual which has been experiencing random mouse/keyboard input
problems. Fingers crossed that your patch will fix this issue for good...
Hi Mark,

I am not sure if this patch helps with the original issue you reported --
random movements of the mouse. If it does help, that's awesome, but I can't
explain it.

It is only supposed to address OS not seeing the keyboard / mouse on reboot.

Does anyone see any problem with the above patch?

Thanks,
Dinesh Subhraveti

Loading...