fix: serial input blocking — timer-polled UART RX fallback
Root cause: IOAPIC edge-triggered delivery for COM1 IRQ 4 never
fires in QEMU i440FX. The UART IRQ line state during the PIC→IOAPIC
transition is undefined — if the line is already HIGH when the
IOAPIC starts watching, no rising edge is ever detected, permanently
blocking serial input.
Attempted fixes that did NOT work:
- hal_uart_drain_rx() after IOAPIC routing (drain FIFO + IIR + MSR)
- FIFO trigger level 14→1 byte (eliminate character timeout dependency)
- IER disable→drain→re-enable sequencing around IOAPIC route
Fix: poll UART RX in the timer tick handler (100Hz). hal_uart_poll_rx()
checks LSR bit 0 and dispatches pending characters through the existing
rx_callback chain (tty_input_char). This gives ≤10ms latency for serial
input — imperceptible for interactive use.
The IRQ-driven path (uart_irq_handler at vector 36) remains active as
a fast path for platforms where IOAPIC edge detection works correctly.
Also adds tests/test_serial_input.exp: automated expect-based test that
boots /bin/sh with console=serial and verifies typed commands execute.