I compiled the latest git snapshot (tag: v2.6.0-rc4, calling itself 2.5.94; with GTK frontend) and could only half-reproduce the bug; keys do not longer "jam", but arrow keys are still captured twice. I woudn't make much of that difference; this bug seems very timing-sensitive. It could be that the GTK frontend adds sufficient latency to the interface to avoid triggering it. I enabled some debugging switches and recompiled both QEMU and the latest git snapshot of SeaBIOS (1.9.0-127; commit c8e105a4d5e52e8e7539ab1f2cd07ebe0ae9033a). This is what I got when running programs affected by this bug: (key press) [qemu ] ps2_queue(0xe0) [qemu ] ps2_queue(0x4d) (IRQ1) [qemu ] KBD: kbd: read data=0xe0 ← (***) [seabios] handle_09 [qemu ] KBD: kbd: read status=0x1d [qemu ] KBD: kbd: read data=0x4d [seabios] i8042_command cmd=ae [seabios] i8042_wait_write [qemu ] KBD: kbd: read status=0x1c [qemu ] KBD: kbd: write cmd=0xae (IRQ1) [qemu ] KBD: kbd: read data=0x4d ← (***) [seabios] handle_09 [qemu ] KBD: kbd: read status=0x1c [qemu ] KBD: kbd: read data=0x4d [seabios] i8042_command cmd=ae [seabios] i8042_wait_write [qemu ] KBD: kbd: read status=0x1c [qemu ] KBD: kbd: write cmd=0xae Reads marked (***) do not appear when running unaffected programs. So it appears something is making reads from the keyboard controller before SeaBIOS has a chance to put scancodes in the ring buffer. And indeed: DJGPP libc installs a custom IRQ1 handler which does it to detect whether it should raise SIGINT in response to Ctrl+C; it can be found in the file src/libc/go32/exceptn.S in the djcrx package[1]. Free Pascal incorporates this handler into its RTL with almost no changes; it's found in rtl/go32v2/exceptn.as[2]. I also noticed I can reproduce this bug with Borland Pascal 7; lo and behold, the Turbo Vision library does something similar. SeaBIOS gets extra confused when I send some mouse events to QEMU (grab the mouse, move it around, ungrab); it reacts with a "ps2 keyboard irq but found mouse data?!" message and refuses to put keys in the ring buffer until the queue of mouse events becomes empty. That's the culprit, I think. It also explains why the bug doesn't appear under Windows; because port 0x60 reads from DPMI are simulated, they don't correspond to actual port 0x60 reads in the guest. I don't know what the fix ought be; documentation about the i8042 that I found is unclear about what real hardware does in this case. If I'm reading the code correctly, DOSEMU[3] (also the DOSEMU2 fork[4]), DOSBox[5], Bochs[6] and VirtualBox[7] keep one value to be read from 0x60 at until the next interrupt, avoiding the issue. [1] ; function ___djgpp_kbd_hdlr [2] ; function ___djgpp_kbd_hdlr [3] [4] [5] [6] [7]