Skip to content

clang-tidy bug-class cleanup + VirtualBox bring-up & firmware-robustness hardening#266

Merged
Krilliac merged 5 commits into
mainfrom
claude/clang-tidy-advisory-cleanup
May 16, 2026
Merged

clang-tidy bug-class cleanup + VirtualBox bring-up & firmware-robustness hardening#266
Krilliac merged 5 commits into
mainfrom
claude/clang-tidy-advisory-cleanup

Conversation

@Krilliac
Copy link
Copy Markdown
Owner

@Krilliac Krilliac commented May 16, 2026

Summary

This PR started as the advisory clang-tidy bug-class cleanup + the initial ACPI direct-map fix, and was extended (at the requester's direction, one consolidated PR) with a sequence of VirtualBox bring-up + firmware-robustness fixes discovered by actually booting DuetOS under VirtualBox for the first time. Every fix has a documented root cause and is general hardening (helps quirky real UEFI / other VMs), not a VBox-specific hack. Net result: DuetOS went from instant-BSOD under VBox to a booting desktop at 1024×768 with a working keyboard.

Commits

  1. win32: clear mingw warnings in PE smoke fixtures (already in win32: clear mingw warnings in PE smoke fixtures #265-era) / kernel: clear advisory clang-tidy bug-class findings + fix ACPI direct-map assumption — the original scope: ~45 bug-class clang-tidy findings fixed (argument-comment, branch-clone incl. a real latent bug, inconsistent-param-name, macro-parens, 16 dynamic-static-initializers via constinit, 6 enum-size), 894 advisory style findings deliberately left; plus AcpiMapPhys/PhysToHeader so ACPI tables above the 1 GiB direct map are reachable.

  2. acpi: VirtualBox bring-up — RSDT fallback, shared mapper, table-dump diag — incomplete-XSDT → RSDT fallback (VBox lists the MADT only in the legacy RSDT); promote the mapper to one shared AcpiMapTable API used by aml.cpp too (one source of truth); one-shot boot ACPI table dump (gated diagnostic).

  3. boot: gate pathologically-slow self-tests under VMM/debug; fix DuetFS lz4 boundauth_pentest / PasswordHashSelfTest (Argon2id) / duetfs v5+ self-test are pathologically slow unoptimised and wedged debug/VBox boots; gated on IsEmulator() || kIsDebugBuild (VBox hides the hypervisor CPUID leaf so IsEmulator() alone was insufficient). Also a genuine latent fix: the DuetFS LZ4 self-test asserted the canonical LZ4 bound but the backend is lz4_flex (~1.1·n) — now trusts the impl's reported bound.

  4. drivers: PS/2 + IOAPIC virtualization robustness — explicitly clear the 8042 translation bit (keyboard is forced to Set 1; VBox firmware left translation on → mangled keymap); cut the PS/2-mouse poll cap (each Inb is a VM-exit under virtualization → ~30 s apparent hang on VBox's silent aux channel); IOAPIC route read-back diagnostic (Debug-gated).

  5. boot/video: request 1024x768x32 framebuffer; add bringup-tail markers — Multiboot2 framebuffer tag was 0/0/0 ("any"); VBox resolves that to 640×480 (desktop unusably oversized) — now requests a concrete universal mode. Plus [bringup-tail] bracket markers that localized a silent boot hang.

Verification

  • x86_64-release + x86_64-debug: zero warnings, zero errors
  • clang-format clean on all changed C/C++ (.S exempt per project policy)
  • clang-tidy bug-class findings: 0 remaining (advisory style findings intentionally untouched)
  • QEMU full boot=desktop reaches the composed desktop and spawns kbd-reader
  • VirtualBox: boots from instant-BSOD → GUI login at 1024×768 with a correctly-mapped working keyboard

Known follow-ups (out of scope, tracked separately)

  • Login panel 1 Hz repaint flicker (compositor double-buffering / repaint-throttle — partly VBox-framebuffer-specific).
  • PS/2 mouse: VBox's emulated aux channel doesn't respond; needs an aux-init quirk or USB-HID input (substantial new driver).
  • Post-BSOD "waiting for keypress" busy-poll (missing HLT).
  • The pre-existing release-asserts/release-lto bring-up smoke flake (documented TCG-timing heuristic, unrelated to this diff).

🤖 Generated with Claude Code

Krilliac and others added 5 commits May 16, 2026 13:02
…t-map assumption

Two changes, combined per request:

1. clang-tidy bug-class cleanup (the ~45 non-style advisory findings;
   the 894 readability-braces / loop-convert / using-namespace style
   findings are intentionally left — they are advisory-only noise):

   - bugprone-argument-comment (12): net_smoke.cpp / tls.cpp call-site
     /*name=*/ comments updated to the real parameter names.
   - readability-inconsistent-declaration-parameter-name (5): mlme.h /
     eapol.h / fourway.h declarations aligned to their definitions.
   - bugprone-branch-clone (3): drsh_desktop.cpp removed a dead,
     immediately-overwritten buggy `(p[3]!=0)?false:false` assignment
     (real latent bug); tcp.cpp / beacon.cpp merged genuinely-shared
     branch bodies with no behaviour change (beacon.cpp also drops the
     now-redundant has_psk to avoid -Werror=unused).
   - bugprone-implicit-widening-of-multiplication-result (1 site):
     drsh_desktop.cpp framebuffer offset math widened to u64 before
     the multiplies.
   - bugprone-macro-parentheses (1): result.h RESULT_TRY_ASSIGN — decl
     is a declarator, not an expression; documented NOLINT.
   - bugprone-dynamic-static-initializers (16): tcp_internal.h /
     shell_internal.h statics made `constinit` at both the extern
     decls and definitions (this surfaced + fixed real non-constant
     init of Tcb/Stats, which now use explicit value-init). The check
     still flags extern-in-header so a documented NOLINT closes it —
     the freestanding hazard itself is eliminated by constinit.
   - performance-enum-size (6): VfsBackend->u8, KObjectType->u16,
     ErrorCode->u8 (internal, no wire format); Cap / FwPackageFamily /
     FwPackageFlags kept wide with documented NOLINT (ABI-adjacent /
     serialized field widths — narrowing them would be wrong).

2. ACPI: stop assuming every ACPI table lives below the 1 GiB direct
   map. PhysToHeader() now routes through a cached AcpiMapPhys() that
   uses PhysToVirt when in range and MapMmio otherwise. QEMU/OVMF
   (tables low) is unchanged; VirtualBox parks the XSDT near the top of
   2 GiB RAM, which previously hard-panicked "PhysToVirt called outside
   direct map" at boot. Resolves the long-standing acpi.h TODO. DSDT /
   SSDT scanners routed through the same helper; acpi.h scope note
   updated.

Verified: x86_64-release + x86_64-debug build zero-warning/zero-error,
ctest green, QEMU bringup smoke reaches bringup-complete with no fatal
sentinels. clang-tidy bug-class findings: 0 remaining. The MapMmio ACPI
path only triggers on VirtualBox-style high table placement (not QEMU),
so it is validated on real VirtualBox boot.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…diag

Continues the ACPI direct-map work from the previous commit. Booting
DuetOS under VirtualBox (vs the QEMU/OVMF the parser was written
against) surfaced three more firmware-shape incompatibilities, all
fixed here. None are VBox-specific hacks — each hardens the parser for
quirky real UEFI too.

- Incomplete XSDT → RSDT fallback. VirtualBox ships an XSDT that lists
  only FADT + SSDT and puts the MADT (and the rest) only in the legacy
  RSDT. FindTable() used the XSDT exclusively on ACPI 2.0+ and returned
  nullptr on a miss; it now falls through to scan the RSDT before
  giving up. The ACPI spec says the two roots should agree; firmware in
  the wild does not always honour that.

- Shared AcpiMapTable(). The DSDT/SSDT readers in aml.cpp called
  mm::PhysToVirt directly, which panics for the >1 GiB tables VBox/real
  UEFI park high. Promoted the file-local AcpiMapPhys to a single named
  API (acpi.h) so every ACPI TU resolves table addresses through the
  same direct-map / cached-MMIO fallback. One source of truth.

- AcpiDiagDumpTables(): one-shot, boot-only dump of the RSDP + both
  root tables (XSDT and RSDT) with every entry's phys + 4-char
  signature. WARN-level so it lands in a serial capture; kept (gated by
  the once-at-boot call site) because non-QEMU firmware bring-up will
  keep needing exactly this layout dump. acpi.h scope note updated to
  match the new behaviour.

Verified: x86_64-release + x86_64-debug build zero-warning/zero-error;
QEMU full boot reaches the desktop; VirtualBox boots past ACPI parse
(previously hard-panicked "PhysToVirt called outside direct map" / "MADT
not found").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… lz4 bound

A class of boot-time self-tests assumed an operation that is cheap on
bare metal / QEMU-TCG is cheap everywhere. Under a hardware-virtualised
host (VirtualBox) — or in an unoptimised debug build — they are
pathologically slow and wedge boot for minutes, which under VBox
manifested as the kernel never reaching the input-consumer spawn (no
keyboard). The existing gate was arch::IsEmulator(), but VirtualBox
hides the hypervisor CPUID leaf by default so IsEmulator() reads false
and the gate never fired. Add a kIsDebugBuild guard alongside it so dev
boots stay usable regardless of whether hypervisor detection succeeds.

- auth_pentest.cpp: the brute-force probe issues 8× PBKDF2-HMAC-
  SHA256(100k); skip under IsEmulator() OR kIsDebugBuild.
- password_hash.cpp: PasswordHashSelfTest's random-salt arm runs
  2×create + 2×verify and PasswordHashCreate defaults to Argon2id
  (memory-hard). The deterministic create/verify correctness is already
  covered by the PBKDF2 KAT directly above it, so skip the Argon2id arm
  in debug builds (kept in full for release / bare metal).
- duetfs.cpp: the v5+ self-test surface is documented in-tree as
  "known-wedged on KVM, not fully diagnosed" and was already skipped
  under IsEmulator(); extend the gate with kIsDebugBuild for the same
  reason as above.
- duetfs.cpp: separately, fix a genuine latent bug in the LZ4 self-
  test — it asserted bound < kPayloadLen+256 assuming the canonical LZ4
  bound (n + n/255 + 16), but the backend is lz4_flex
  get_maximum_output_size + 4 (~1.1·n), which legitimately exceeds both
  the old ceiling and the old 4352-byte buffer. Trust the impl's
  reported bound as the source of truth; size the buffer from it and
  sanity-check only that it is positive and ≤ 2·n+64 (never a false
  positive for any LZ4-family compressor, still catches 0 / garbage).

Verified: both presets build clean; QEMU full boot reaches the desktop
and spawns kbd-reader; VBox debug boot now reaches the GUI login with a
working keyboard instead of hanging/​panicking in these self-tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PS/2 input bring-up made bare-metal-shaped assumptions that break on a
hardware-virtualised host. All three fixes are correct hardening for
real hardware too.

- ps2kbd.cpp: explicitly clear the 8042 first-port translation bit
  (config byte bit 6). Step 8 already forces the keyboard into Set 1,
  so the controller must NOT also run a Set-2→Set-1 translation pass —
  with it on, every Set-1 code is mangled through the translation
  table. The driver previously "left translation whatever firmware set
  it to"; SeaBIOS/OVMF leave it off, VirtualBox leaves it on, which
  produced a completely wrong keymap. Make it deterministic.

- ps2mouse.cpp: cut the 8042 poll cap from 1,000,000 to 50,000. On
  bare metal an Inb is a few cycles so the old cap was ~tens of ms;
  under hardware virtualization every Inb on the 8042 ports is a
  VM-exit (~0.5-1 us), so the old cap was ~1 s PER wait, and a silent
  (mouse-absent) VBox aux channel stacked dozens of them into a ~30 s
  apparent boot hang before the "no PS/2 mouse" bail. A present mouse
  ACKs in microseconds, so 50k keeps an ample margin while bounding the
  absent-device path to a fraction of a second.

- ioapic.cpp: IoApicRoute now reads the redirection entry back and
  logs gsi/vector/wrote/readback at Debug level (kept, gated) — some
  emulated IOAPICs silently drop writes to certain entries; this proves
  whether a route actually latched without an operator re-adding
  prints. Visible in debug builds, silent in release.

Verified: both presets build clean; under VirtualBox the keyboard now
maps correctly and PS/2 init no longer dominates boot time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- boot.S: the Multiboot2 framebuffer request tag asked for 0/0/0
  ("any linear framebuffer"). GRUB resolves "any" to 1024x768 on QEMU
  std-vga but to the lowest VBE mode (640x480) under VirtualBox, which
  renders the desktop into a tiny buffer VBox then upscales — the UI
  was unusably oversized. Request a concrete, universally-supported
  1024x768x32 (in every VBE/VBoxVGA mode list, fits default VBox VRAM).
  Flags stay optional so a host without the mode still boots to serial.

- main.cpp: add three [bringup-tail] serial markers (kernel-services
  done / devices done / kbd-reader spawned bracket) around the late
  boot phases. These were the bisection tool that localized a silent
  post-self-test boot hang to BootBringupDevices; kept as cheap,
  one-shot structural sentinels (the boot already emits this class of
  marker) so the next silent-hang regression is localizable without
  re-instrumenting.

Verified: both presets build clean (.S is hand-formatted, exempt from
clang-format per project policy); QEMU and VirtualBox both bring up the
desktop at 1024x768.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Krilliac Krilliac changed the title kernel: clear advisory clang-tidy bug-class findings + fix ACPI direct-map assumption clang-tidy bug-class cleanup + VirtualBox bring-up & firmware-robustness hardening May 16, 2026
@Krilliac Krilliac merged commit 0b51718 into main May 16, 2026
18 checks passed
@Krilliac Krilliac deleted the claude/clang-tidy-advisory-cleanup branch May 16, 2026 20:42
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