vbox-followup: kill 1 Hz login flicker + fix dead PS/2 mouse#267
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two VBox-bring-up follow-up fixes (remaining issues from PR #266).
1 Hz login flicker (
kernel/security/login.cpp)GuiRepaintfull-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 inFramebufferBeginCompose()/FramebufferEndCompose()so the whole panel composites into the offscreen shadow surface and lands in a single blit — exactly the flowDesktopComposealready uses. No-op fallback to direct mode if the shadow allocator is unavailable. Login repaint andDesktopComposeare mutually exclusive (the tickercontinues pastDesktopComposewhile 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:
Ps2MouseInitruns afterPs2KeyboardInithas unmasked IRQ 1, then does a polled 8042 controller dialogue. Every non-aux response it polls for (the0xA9port-2 test result,ReadConfigByte's reply, device ACKs) also raises the keyboard IRQ; the keyboard ISR reads port0x60first and rings it as a scancode, so the mouse init'sTryWaitOutputFullspins 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-IFCli()/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:
ps2mousenow reachesavailable=1(ACKed enable-reporting, IOAPIC-routed) instead of the no-response bail.Post-BSOD HLT — investigated, deliberately not changed
BsodRenderholdscliwith a documented rationale (a panicked kernel re-entering the keyboard ISR is worse than a spin). A plainhltthere deadlocks (no interrupt ever wakes it);sti; hltreintroduces 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 direct0x64poll 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
x86_64-debug+x86_64-releaseclean under-Werror;clang-formatclean.ctest100% 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).🤖 Generated with Claude Code