Skip to content

vbox-followup: kill 1 Hz login flicker + fix dead PS/2 mouse#267

Merged
Krilliac merged 2 commits into
mainfrom
claude/vbox-followup-flicker-mouse-hlt
May 16, 2026
Merged

vbox-followup: kill 1 Hz login flicker + fix dead PS/2 mouse#267
Krilliac merged 2 commits into
mainfrom
claude/vbox-followup-flicker-mouse-hlt

Conversation

@Krilliac
Copy link
Copy Markdown
Owner

Two VBox-bring-up follow-up fixes (remaining issues from PR #266).

1 Hz login flicker (kernel/security/login.cpp)

GuiRepaint full-screen-gradient-filled the live framebuffer, painted the panel on top, then presented. On un-coalesced host framebuffers (VirtualBox) the gradient-only intermediate frame showed for ~1 frame at the ui-ticker's 1 Hz cadence, reading as a flicker. Now wrapped in FramebufferBeginCompose() / FramebufferEndCompose() so the whole panel composites into the offscreen shadow surface and lands in a single blit — exactly the flow DesktopCompose already uses. No-op fallback to direct mode if the shadow allocator is unavailable. Login repaint and DesktopCompose are mutually exclusive (the ticker continues past DesktopCompose while login is active; the kbd reader routes login keys to login handlers), so there is no nested-compose hazard.

Dead PS/2 mouse (kernel/drivers/input/ps2mouse.cpp)

Root cause: Ps2MouseInit runs after Ps2KeyboardInit has unmasked IRQ 1, then does a polled 8042 controller dialogue. Every non-aux response it polls for (the 0xA9 port-2 test result, ReadConfigByte's reply, device ACKs) also raises the keyboard IRQ; the keyboard ISR reads port 0x60 first and rings it as a scancode, so the mouse init's TryWaitOutputFull spins to its cap and bails (port-2 self-test no response (no PS/2 mouse?)). QEMU's IRQ timing happened not to bite; VirtualBox's makes the steal deterministic — the reported "PS/2 mouse dead in VBox" symptom.

Fix: steps 1–5 split into Ps2MouseControllerBringup() (one clean exit), and steps 1–6 now run under a saved-IF Cli()/Sti() window so the live keyboard ISR can't steal the polled controller responses. The dialogue is bounded spin-polls + register writes (no sleep/block), so a CLI window is safe; IF is saved/restored rather than unconditionally re-enabled so a future caller with interrupts already off isn't surprised.

Verified under QEMU: ps2mouse now reaches available=1 (ACKed enable-reporting, IOAPIC-routed) instead of the no-response bail.

Post-BSOD HLT — investigated, deliberately not changed

BsodRender holds cli with a documented rationale (a panicked kernel re-entering the keyboard ISR is worse than a spin). A plain hlt there deadlocks (no interrupt ever wakes it); sti; hlt reintroduces the exact ISR-reentry the author rejected; routing through the keyboard ring couples the BSOD to driver state and breaks on the IDT-corruption panics where the direct 0x64 poll is the only robust exit. A busy-poll panic screen is conventional (Linux's panic loop does the same). The prior "one-line fix" note underestimated the CLI constraint; left as-is intentionally.

Verification

  • Builds: x86_64-debug + x86_64-release clean under -Werror; clang-format clean.
  • Tests: ctest 100% pass; QEMU headless smoke clean, no new sentinels (the [E]/[W] lines are pre-existing self-tests, confirmed against a pre-change VBox serial log).
  • VBox-specific paths (the IRQ-timing that was the actual mouse bug, and the visual flicker) need a real VBox boot to confirm end-to-end.

🤖 Generated with Claude Code

Krilliac and others added 2 commits May 16, 2026 16:12
Ps2MouseInit runs after Ps2KeyboardInit has already unmasked IRQ 1,
then does a polled 8042 controller dialogue (0xA9 port-2 test,
ReadConfigByte, device ACKs). Every non-aux response byte it polls
for also raises the keyboard IRQ; the keyboard ISR reads port 0x60
first and pushes the byte into the scancode ring, so the mouse
init's TryWaitOutputFull spins to its cap and bails. On QEMU the
race window happened not to bite; on VirtualBox the controller's
IRQ timing makes the steal deterministic — the "port-2 self-test
no response (no PS/2 mouse?)" boot bail with the aux device
present and configured.

Split steps 1-5 into Ps2MouseControllerBringup() (one clean exit)
and run steps 1-6 under a saved-IF CLI window so the live keyboard
ISR can't steal the polled controller responses. The whole
dialogue is bounded spin-polls + register writes (no sleep/block),
so a CLI window is safe; IF is saved/restored rather than
unconditionally re-enabled so a future caller with interrupts
already off isn't surprised.

Verified under QEMU: ps2mouse now reaches available=1 (ACKed
enable-reporting, IOAPIC-routed) instead of the no-response bail.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The ui-ticker repaints the GUI login panel once a second via
LoginRepaint -> GuiRepaint, which issued a full-screen gradient
fill straight to the live framebuffer, then painted the panel on
top, then presented. On un-coalesced host framebuffers (VBox) the
gradient-only intermediate frame is visible on its own, reading as
a 1 Hz flicker.

Wrap GuiRepaint's draw sequence in FramebufferBeginCompose() /
FramebufferEndCompose() so the whole panel composites into the
offscreen shadow surface and lands in a single blit, exactly like
DesktopCompose already does. No-op fallback to direct mode if the
shadow allocator is unavailable. Login repaint and DesktopCompose
are mutually exclusive (the ticker continues past DesktopCompose
while login is active; the kbd reader routes login keys to login
handlers), so there is no nested-compose hazard.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Krilliac Krilliac merged commit 140f762 into main May 16, 2026
38 checks passed
@Krilliac Krilliac deleted the claude/vbox-followup-flicker-mouse-hlt branch May 16, 2026 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant