Files
Asuro/doc/planning/x86_64.md
T
Aaron e69b134bff
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is passing
Integrate x86_64 desktop boot and extend VirtualBox validation
2026-11-08 09:02:34 +00:00

580 lines
34 KiB
Markdown

# x86-64 migration
## Status
The x86-64 target boots into Pascal with exception handling, physical/virtual
allocation, the shared heap, PIC/PIT interrupts and tested kernel-context
preemption. Fatal faults report over COM1.
The native desktop, terminal, storage, E1000 networking and WASM runtime now run.
The existing x86 target remains the default.
## Architecture boundaries and reuse
Follow the namespace convention in [namespace.md](namespace.md): architecture
units live under `src/arch/<architecture>/` and use `arch.<architecture>.*` names.
The compiler-required `system.pas` retains its special name.
- `src/arch/x86_64/boot/stub.asm`: 32-bit Multiboot entry and long-mode transition.
- `src/arch/x86_64/arch.x86_64.boot.pas`: bootstrap entry and serial self-checks.
- `src/arch/x86_64/system.pas`: minimal compiler runtime definitions.
- `src/arch/x86_64/arch.x86_64.isr.pas`: IDT/TSS setup, frame validation, and
allocation-free exception reporting.
- `src/arch/x86_64/isr/entry.asm`: generated entry stubs, register/FX save and
restore, `iretq`, emergency stacks, and controlled fault probes.
- `src/debug/debug.early.pas`: reusable architecture-independent diagnostic
formatting, supplied with a character sink by `arch.x86_64.debug`.
- `src/arch/common/system.types.inc`: shared scalar/compiler definitions extracted
from the existing system unit; native widths follow the selected CPU target.
- `toolchain/target.sh`: target selection shared by the existing build steps.
- `toolchain/x86_64/linker.script`: bootstrap address layout.
Do not copy the i386 kernel, drivers, heap, scheduler policy, or runtime wholesale.
As each subsystem is enabled, retain portable logic in its existing namespace
and put architecture-specific operations behind the appropriate architecture
interface. External `lvgl/` and `wasuro/` sources must remain unchanged.
## Build and boot
Rebuild the builder image when first adding the native x86-64 FPC compiler:
```powershell
docker-compose down --remove-orphans
docker-compose build builder
```
Build x86-64 using the normal build command with an explicit target:
```powershell
$env:ASURO_ARCH = 'x86_64'
docker-compose run builder | Tee-Object -FilePath .\build.log
Remove-Item Env:ASURO_ARCH
Select-String -Path .\build.log -Pattern "Error|Fatal|Success|No errors|Failed" -CaseSensitive
```
Outputs are `Asuro-x86_64.iso`, `bin/x86_64/kernel.bin`, and `lib/x86_64/`.
Without `ASURO_ARCH`, the existing x86 build still produces `Asuro.iso`,
`bin/kernel.bin`, and `lib/`. Cleaning and linking only consider the selected
target's objects. The x86 compiler search path excludes `src/arch/x86_64`.
Use VirtualBox for runtime validation. With the configured Asuro VM stopped,
select `Asuro-x86_64.iso` as its optical medium, then start it through the normal
VM workflow and read `C:\Temp\asuro.log`. Restore the original optical medium
after testing. The normal image enumerates storage and mounts attached filesystems; boot checks read attached disks without writing them.
Expected serial output:
```text
ASURO x86_64: IDT/TSS ready; DF/NMI/MC emergency stacks installed
ASURO x86_64: entered Pascal
PASS: long mode, Multiboot handoff, 64-bit Pascal types
PASS: INT3 frame, GPRs, RFLAGS, x87/SSE and IRETQ
PASS: page-fault error code, CR2 and IRETQ recovery
EXCEPTION_TESTS_PASSED=0000000000000002
EXCEPTION_TESTS_FAILED=0000000000000000
ASURO x86_64: desktop ready
```
An early single `C` means CPUID/long-mode support is unavailable; `B` means an
invalid Multiboot magic value. The Pascal checks validate the handoff magic,
a non-null info pointer, native/fixed type widths, wide arithmetic, and EFER.LMA.
### Repeatable VirtualBox fault checks
The default build runs two returning self-tests. `INT3` verifies the saved frame,
all 15 general registers including high halves, CF/DF, x87 and XMM0/XMM15 state,
and `iretq`. The handler intentionally destroys FX state before the return path
restores it. A write to unmapped `0x100000000` verifies hardware error code `2`,
CR2, and recovery by changing RIP only for the exact expected probe.
Use the bounded test harness with the configured VM powered off:
```powershell
.\toolchain\x86_64\test_boot.ps1 -Test none
```
For deliberately fatal tests, select `ud`, `pf`, or `df` when building, then use
the matching harness option. For example:
```powershell
$env:ASURO_ARCH = 'x86_64'
$env:ASURO_BOOT_TEST = 'df'
docker-compose run builder | Tee-Object -FilePath .\build.log
Remove-Item Env:ASURO_BOOT_TEST
Remove-Item Env:ASURO_ARCH
.\toolchain\x86_64\test_boot.ps1 -Test df
```
The harness uses `localenv.json`, temporarily attaches the ISO, starts the VM
through `virtualbox-wrapper.ps1 -command up -Headless -NoMonitor`, validates
serial output, captures registers, stops the VM, and restores the original
optical medium in a `finally` block. The new wrapper switches are optional;
the existing interactive workflow is unchanged. Storage disks are not changed.
Rebuild without `ASURO_BOOT_TEST` after testing to restore the normal image.
## Bootstrap layout and limitations
- GRUB loads the kernel at physical/virtual 1 MiB using explicit Multiboot v1
load-address fields; the payload is ELF64 with a 32-bit assembly entry.
- Six reserved 4 KiB pages hold the PML4, PDPT, and four page directories.
They identity-map the first 4 GiB with 2 MiB leaves.
- A reserved 16 KiB stack is aligned for the SysV AMD64 calling convention.
These bounded early allocations exist before any heap and must remain
reserved when the physical allocator is introduced.
- Paging, PAE, long mode, x87, and SSE2 support are enabled before calling Pascal.
- A 256-entry IDT uses normalized 64-bit frames. TSS IST1 supplies a 16 KiB
double-fault stack; IST2 and IST3 supply separate 8 KiB NMI and machine-check
stacks. The 4 KiB IDT, 104-byte TSS, and emergency stacks are bounded early
reservations before the allocator exists. Stack guard pages remain future work.
- Entry preserves GPRs and captures CR2 before Pascal code. It clears DF, aligns
the call stack, and saves/restores x87/SSE state using FXSAVE64/FXRSTOR64.
AVX/OSXSAVE and lazy-FPU switching are not enabled. Future changes must extend
this state policy before enabling those features.
- IRQ0 is enabled during timer and context tests, then masked before the final
halt. PIC acknowledgement and spurious IRQ7/15 handling are implemented.
General driver hooks and APIC/SMP remain future work.
- The low identity map is temporary. It is not a final process address-space
design and does not enforce page-level W^X. New heap mappings use 4 KiB pages
at `0xFFFF800000000000`, spanning up to 16 GiB with NX when supported.
Their backing frames can reside above 4 GiB.
- Unsupported runtime operations intentionally fail to link rather than silently
delegating to a hosted runtime or pretending to succeed.
## Remaining migration work
| Area | Existing assumptions / next work |
|---|---|
| Runtime | Keep compiler metadata shared; initialization dispatch is shared; implement further x86-64 helpers as consumers are ported. |
| Common kernel entry | `src/asuro.pas` currently imports x86 units; separate common boot sequencing from architecture setup before sharing full initialization. |
| Exceptions | IDT/TSS, IST stacks, normalized frames, diagnostics, and tested `iretq` paths are implemented. NMI/MC injection, user transitions, guard pages, and general IRQ dispatch remain. |
| ABI | Bootstrap interrupt alignment and x87/SSE preservation are tested. Audit red-zone assumptions for each added compiler/library and extend preservation before enabling AVX or lazy-FPU switching. |
| Memory | PMM, VMM and shared heap implemented. Final process layout, guards, MMIO and DMA APIs remain. |
| Scheduler/loader | Shared scheduling, kernel preemption and process lifecycle tested. Process address spaces and executable loading remain. |
| Drivers/storage | Audit `uint32(pointer)` conversions, MMIO and DMA translations, and hardware address limits. Keep disk/USB/controller structures fixed-width. |
| Graphics | VESA calls into V86, which cannot operate in long mode. Initially use a bootloader framebuffer; rebuild LVGL and verify Pascal/C bindings later. |
| Validation | Add deliberate exception tests, allocator checks, preemption checks, and storage tests as their implementations become available. |
Next milestone: port filesystem/console services and complete driver address/DMA
audits. Kernel process lifecycle now uses the shared manager. Do not enable the
desktop/storage stack before its dependencies are ported and tested.
## Validation performed — 2026-11-07
- x86-64 compile, link, GRUB header validation, and ISO generation passed.
- The existing Asuro VirtualBox VM printed all three expected serial lines.
- First-milestone VirtualBox registers showed `CS=0x18`, `CR0=0x80000013`,
`CR3=0x103000`, `CR4=0x620`, and `EFER=0x500` (LME and LMA set).
- Disassembly confirmed 64-bit Pascal code, wide arithmetic, and aligned calls
in the bootstrap. This does not establish interrupt safety for future code.
- The full default x86 build passed, including compilation, linking, ISO, and
documentation generation, with the x86-64 output directory still present.
- The VM was stopped and its original optical medium restored after testing.
- VirtualBox passed the normal boot tests and deliberate invalid-opcode,
page-fault, and double-fault builds. The final write-fault test preserved
error code `2` and CR2 `0x100000000`.
- The exception milestone's normal boot captured `TR=0x20`, confirming the
installed TSS selector, with long mode still active (`EFER=0x500`).
- Double-fault injection set RSP to unmapped `0x100001000`. Diagnostics reported
vector `8`, error `0`, the original RSP, and a frame inside the IST1 stack.
- Fatal exception reports include all 15 GPRs, RIP/CS/RFLAGS/RSP/SS, error code,
CR2, and frame address. CR2 is the last page-fault address and may be stale
for other exception types.
Runtime evidence is saved locally in the ignored `bin/x86_64/boot.log` and
`bin/x86_64/registers.log` files for the first milestone, and `boot-<test>.log` /
`registers-<test>.log` for the exception milestone. Unsupported-CPU boot checks and NMI/MC injection have not yet been performed.
The interrupt-frame and IST layout follows the
[AMD64 System Programming manual, chapter 8](https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24593.pdf).
## Memory, timer and shared scheduling progress
The PMM uses 4 KiB frames and dynamically placed bitmaps, with a 64 GiB management
cap. Boot metadata, modules, kernel ranges, low bootstrap memory and allocator
metadata stay reserved. VMM allocates high virtual arenas and rolls back both
page tables and backing frames on failure. Page tables remain below 4 GiB;
backing frames may reside above it.
`memory.heap` is shared between targets, with native-width pointer/size APIs,
16-byte alignment, overflow rejection and large-allocation rollback.
`memory.bitmap` supplies the common bitmap operations. `boot.multiboot` owns
fixed-width protocol records, with aliases retained in the x86 boot unit.
`arch.common.legacyirq` shares PIC programming and PIT constants.
`io.types` separates data contracts from console initialization. `proc.types`
uses native saved-stack addresses. The existing round-robin/quantum policy now
lives in `proc.scheduler`, called by both the i386 process manager and x86-64
preemption tests. Process creation, messaging, return/exit, resource cleanup and reaping now use
`proc.mgr` on x86-64. Descriptor tables are now active; console commands, executable loading and
full filesystem/controller integration remain unavailable in the bootstrap.
VirtualBox validation has passed at 64 MiB, 2 GiB and 6 GiB. The 6 GiB run mapped,
wrote, read and released RAM above 4 GiB. Tests cover PMM accounting and invalid
frees, VMM rollback under injected allocation failures, heap alignment/zeroing/
large allocations, timer delivery, spurious IRQ7/15, IF preservation and CLI.
Two heap-backed kernel contexts preserve distinct 64-bit registers, x87 and XMM
state across timer preemption, then release their stacks after returning to the
bootstrap context. Only the BSP is active; IRQ exclusion is not an SMP lock.
```powershell
.\toolchain\x86_64\test_boot.ps1 -Test none -MemoryMB 64
.\toolchain\x86_64\test_boot.ps1 -Test none -MemoryMB 6144
```
The harness restores original VM RAM and optical media. Logs use
`bin/x86_64/boot-<test>-<MemoryMB>.log` and matching register filenames; zero means
use the configured RAM. All subsystem `*_TESTS_FAILED` fields must be zero.
PIC handling follows the [Intel 8259A datasheet](https://www.cs.umb.edu/cs341/Intel8259/I8259APIC.pdf).
The final i386 regression build passed compilation, linking, ISO and documentation
steps. VirtualBox reached `Boot complete - halting into IDLE`; reported boot test
suites had zero failures. Evidence: `bin/x86_64/i386-regression.log`.
Fatal UD, write-PF and broken-stack DF tests also passed after the context-return
path was extended. Final normal images are built without fault injection.
## Shared process lifecycle
`proc.mgr` now runs on both targets with native process-pointer slots, stable
monotonic IDs, suspended creation, messaging, exit and resource ownership.
Initial stack layout lives in the architecture context units. x86-64's scheduler
adapter saves the current stack and calls the same scheduler/manager as i386.
A shared reaper process handles destruction on both targets outside IRQ context.
Timer selection and kill requests coalesce worker wakeups; cleanup runs after
registry/resource detachment. The reaper sleeps while there is no pending work.
`core.ds.dynamic` contains the common dynamic-list implementation; existing
`core.ds.lists` exports compatible aliases/wrappers. Native addresses, checked
capacity arithmetic, overlap-safe insertion and empty-list regrowth replace
32-bit arithmetic. Deletion retains capacity; explicit `DL_ShrinkToFit` frees
excess storage without allocating inside every scheduler deletion.
`memory.raw` supplies allocation-free scalar fill/move operations.
Process tests cover suspended publication, high-address lookup, killed tasks
never running, normal return, explicit exit, child notification waking an
awaiting parent, callback reentry without double cleanup, command argument/
stream publication, sleep using the PIT divisor, and restored heap accounting.
The full i386 build and VirtualBox boot passed after these shared changes;
evidence is in `bin/x86_64/i386-lifecycle-regression.log`.
The dedicated reaper revision passed all 15 process/container checks at 64 MiB
and 6 GiB, including the corrected check-before-await notification protocol.
The final i386 build and VirtualBox boot also passed with the shared reaper.
VM RAM and original optical media were restored and the VM was powered off.
## Descriptor tables
The shared `driver.storage.fdtable` now uses native memory operations and balanced
IRQ locking. Every x86-64 process, including system tasks, owns its normal FD
table. Storage protocol types depend on shared record definitions rather than
bringing in the linked-list implementation and its console dependencies.
Close reserves an entry until callbacks and owned-string cleanup finish, rejects
active async references and reference-count overflow, and prevents callback
reentry from freeing it twice. Table teardown atomically rejects new users before
process removal. An exited process with active FD references remains alive; final
completion only wakes the shared reaper, which performs cleanup in process
context. Waiting does not repeatedly scan descriptors on every timer tick.
VirtualBox passes 15 descriptor checks plus 16 lifecycle/container checks,
including an exited child held alive by an async FD reference until another task
releases it. No disk I/O is performed by these bootstrap tests. This validates
FD ownership, not full VFS operation or controller DMA support in long mode.
The descriptor-table revision also passes the complete i386 build and VirtualBox
boot, including the existing storage/VFS suites and normal volume discovery.
Evidence: `bin/x86_64/i386-fd-regression.log`. Original VM settings are restored.
## Shared strings and console command infrastructure
`core.util` memory helpers accept native addresses and sizes, reusing scalar
`memory.raw` operations while retaining i386's existing large-copy REP path.
`core.strings` no longer imports the x86 utility or linked-list implementation;
all string copy addresses are native. Its common tests cover signed 64-bit
minimum formatting, overflowing substring/match bounds, and terminator size
rejection. The x86-64 system unit supplies Double-to-int64 truncation using
CVTTSD2SI without changing rounding control state.
`io.stdio` now builds on both targets: growable buffers, bounded command parsing,
case-insensitive allocation-free lookup, registry growth, ANSI output, and
ECHO/CLEAR/HELP share one implementation. Buffer appends reserve space in bulk
and support self-append across relocation. Allocation failures retain the old
buffer; parser failures release all partially built parameters. Completion
detaches the halt owner before invoking callbacks, allowing safe reentry.
VFS working-directory delegation and VERSION/TIME/REBOOT registration remain
gated until their platform dependencies are integrated. This is command
infrastructure, not yet an interactive keyboard/display/serial shell. No VFS or
storage-controller support is implied by compiling the console unit.
The 64-bit bootstrap runs 162 shared string tests and 17 stdio tests. The process
suite also launches the registered ECHO through `runCommand` with real parsed
arguments and a growable output buffer, bringing it to 17 lifecycle/container
checks. The 6 GiB VirtualBox run verifies scheduled ECHO and physical RAM above
4 GiB. The complete i386 build and boot also pass, including 162 string tests,
stdio tests, normal mounts, and the existing storage/VFS suites. Evidence:
`bin/x86_64/i386-console-regression.log` and the normal x86-64 boot logs.
## Build-selected platform adapters
Shared Pascal units no longer select CPUs with `CPU64`/`CPU386` conditionals.
`ASURO_ARCH` selects a single `src/arch/<target>/platform` directory in the
compiler search path. Both targets implement the same `arch.platform.cpu`,
`arch.platform.memory`, `arch.platform.process`, and
`arch.platform.diagnostics` unit names. Their declarations are shared through
`src/arch/common/platform.*.inc`; implementations delegate to the existing
architecture units. Calls are resolved at compile/link time, with no runtime
architecture selection or function-pointer dispatch.
The bitmap heap, allocation headers, process registry, scheduling policy,
strings, console buffers/parser, and descriptor lifecycle remain single shared
implementations. Native scalar widths live in each selected system unit.
`memory.raw` builds its fill pattern from native word width without a CPU branch.
`arch.x86.startup` now registers heap/process/console startup with the boot
manager. `arch.x86.console` owns VERSION/TIME/REBOOT commands and their driver
dependencies. The x86-64 bootstrap retains its explicit startup sequence.
Unused working-directory wrappers were removed; directory operations belong to VFS.
Existing `DEBUG_LMM` allocator guards and architecture-local fault-injection
build flags remain; these are feature/test options, not architecture selection.
Validation: complete i386 build and VirtualBox boot, including 17 stdio checks,
162 string checks, storage/VFS suites and normal mounts. Evidence:
`bin/x86_64/i386-platform-regression.log`. x86-64 boot validation covers heap,
IRQs, contexts, descriptors, strings, console and scheduled command execution.
The final adapter build also passes the 6 GiB VirtualBox bootstrap, including
physical memory above 4 GiB and all 162 string, 17 console, 15 descriptor,
and 17 lifecycle/container checks. VM RAM and optical media were restored;
the VM is powered off.
Source search paths are discovered recursively from shared roots and the selected
architecture tree, with other architectures excluded. Both targets use the same
compiler invocation; `target.sh` loads compiler options and entry points from
`toolchain/targets/<architecture>.sh`.
Directory arguments are NUL-delimited, sorted, and passed as an array so new
subdirectories and spaces in names do not require compile-script edits. Full
i386 and x86-64 builds pass using this discovery path.
All shared build steps now consume the selected profile: pipeline stages,
assembler format and source roots, C/Pascal compiler options, linker format,
entry points, output locations, optional compiler runtime, and image validation.
`target.sh` loads the profile by filename instead of keeping an architecture
switch. Assembly files, object files, and static libraries are discovered;
the configured assembly entry is linked first to preserve the Multiboot header.
Initialization-table, icon, LVGL, version, and checksum generation use target
settings too. Full i386 and x86-64 builds and VirtualBox boot checks validate
this pipeline; the i386 boot includes normal mounts and existing storage tests.
## Shared unit initialization
Both system units now use `arch/common/system.init.inc` to dispatch the
build-generated INITFINAL table. The x86-64 profile enables the existing
`initcalls` stage, whose packed records use native procedure-pointer widths.
An initialization guard prevents repeat or reentrant dispatch. This also removes
the duplicated table walks from the i386 runtime.
Initializers may set globals or register boot work; they must not require heap,
hardware setup, or dependency ordering. The existing generator enumerates symbols
in object-file order, so actual subsystem startup remains explicitly sequenced
on x86-64 and dependency-ordered by boot.mgr on i386. The full boot manager remains i386-only; the x86-64 composition now starts
the shared storage services explicitly (see storage integration below).
Validation: x86-64 build and 64 MiB VirtualBox boot passed, including a real
Pascal initialization section checked after two calls to system.init. The full
i386 build and VirtualBox boot also passed, with 54 initialization entries,
normal volume mounts, and zero failures in the reported regression suites.
## Shared filesystem foundations
The shared FNV-1a hashes, hash map, managed/string lists, path syntax, and
filesystem registry now compile and run in long mode. String-list slots hold
native pointers; hash inputs and memory-copy addresses no longer truncate to
32 bits. Hash replacement preserves the entry count, rehashing links each item
in constant time, and container allocation failures leave published state intact.
Linked-list insertion supports the end position and string splitting shares one
implementation with rollback on allocation failure.
`driver.storage.path` provides caller-owned absolute and normalized paths without
volume or driver dependencies. VFS delegates to this implementation on i386.
Normalization scans into one allocated output buffer, handling repeated slashes,
dot segments, and parent traversal without climbing above root. It is lexical;
symlink resolution remains VFS work.
The filesystem registry uses native record copies, handles empty registries,
and traverses linked records directly for linear searches/probes. Its boot
registration lives in arch.x86.startup; x86-64 initializes it explicitly.
Registry tests invoke an identify callback using heap-backed volume/driver
records and restore the existing registry after the test.
New shared checks: 9 FNV-1a, 47 hash-map, 8 list, 15 path, and 9 registry checks.
These foundation checks preceded the storage integration described below.
The shared contiguous FIFO and I/O request pool also run on x86-64. Queue
addresses and byte-size calculations use native widths, capacity growth checks
for overflow/allocation failure, and zero-sized elements are rejected. Request
pool initialization and free-list changes use arch.platform.cpu IRQ exclusion.
Pool node recovery uses the actual request-field offset instead of assuming a
pointer-sized prefix. The bounded, heap-backed pool retains its existing
512-request capacity and lifetime.
The 6 GiB VirtualBox run passes 22 CFIFO and 4 request-pool checks in addition
to the filesystem-foundation suites. Tests cover queue compaction/growth,
native pointer payloads, request-pool exhaustion/reuse, and callback/data copies.
Hardware storage validation is covered by the subsequent integration below.
Final validation for this batch: both target builds pass. The x86-64 VirtualBox
bootstrap passes at 64 MiB; the 6 GiB run also passes the above-4-GiB physical
memory check. i386 reaches idle with all 114 shared foundation checks passing,
all 130 VFS checks passing, normal ISO9660/FAT32/EXT2 mounts, and zero failures
in the reported storage/controller suites. VM RAM and optical media are restored
and the VM is powered off. Logs remain in bin/x86_64/ (ignored).
## Shared storage integration
The x86-64 boot now starts PCI, AHCI, the shared storage request manager, volume
manager, VFS, ISO9660, FAT32 and EXT2. Boot registration belongs to target startup
units. Shared code uses build-selected CPU, memory, timer and interrupt adapters;
there are no CPU conditionals or duplicated filesystem implementations.
AHCI command lists and FIS buffers use native virtual addresses and full physical
addresses. Each command table fits within one physical page. PRDs translate every
4 KiB page, coalesce contiguous physical runs and retain upper address bits.
Controllers lacking 64-bit DMA reject inaccessible structures and buffers rather
than truncating addresses. Unsupported 32-bit-only controllers do not yet have
bounce-buffer support. The descriptor count remains bounded at 32.
PCI driver callbacks receive persistent device records rather than stack locals.
Multifunction probing visits functions 1 through 7. IRQ/timer callbacks use the
existing i386 interrupt infrastructure or the x86-64 PIC dispatch implementation.
MMIO currently uses the low 4 GiB mapping; this is not general high-BAR support.
VFS, filesystem buffers, volume slots and controller references preserve native
pointer widths. EXT2's worker starts before blocking filesystem operations, with
scheduler interrupts enabled. Filesystem registration follows the i386 probe
order so stale FAT signatures do not take precedence over EXT2 identification.
FAT32 now falls back to the space required by a write when optional preallocation
cannot fit, instead of incorrectly returning disk-full.
VirtualBox validation at 64 MiB and 6 GiB passes:
- 130 shared VFS checks and 34 AHCI checks.
- 123 storage metadata/filesystem checks, including heap-backed FAT32 and EXT2
format, file creation, cross-block write, close/reopen, unaligned read-back,
persisted size and volume cleanup. No attached disk is written by these tests.
- Actual ISO9660, FAT32 and EXT2 mounts through the AHCI controller.
- A 4096-byte VFS read of the ISO's ELF64 kernel with header validation.
- At 6 GiB, sector reads into physical RAM above 4 GiB compared byte-for-byte
against ordinary-buffer reads from every attached storage device.
The boot harness requires the new failure counters and content-read marker; a
high-memory run must also complete the high-DMA comparison. Evidence is saved in
`bin/x86_64/boot-none-64.log` and `bin/x86_64/boot-none-6144.log`.
This completes the tested AHCI/filesystem path, not the entire OS port. The
x86-64 image now continues into the desktop and shared application startup. Remaining USB controllers still require porting and validation. Disk LBAs
and file sizes retain the existing storage API's 32-bit limits.
Final i386 regression also passes: the complete image reaches idle with 123
metadata/filesystem checks, 130 VFS checks, 34 AHCI checks and the existing USB,
controller, storage and core suites reporting zero failures. Early-boot tests
use private filesystem descriptors with synchronous transfer hooks; scheduled
x86-64 tests keep the normal async hooks and exercise the EXT2 worker. The final
6 GiB x86-64 image passes the same 123 checks and the high-DMA comparison.
VirtualBox is powered off with its original 2048 MiB RAM and Asuro.iso restored.
## USB core and OHCI bring-up
The shared USB types, descriptor parsing, controller/device registry and hub
logic now use native pointers and platform adapters. Aligned allocations store
a native-width allocation header and reject invalid alignment and size overflow.
Device-list slots retain full pointers, empty-list loops are bounded, and failed
controller registration rolls back its allocation. Tests isolate registry state
under IRQ exclusion and verify that their allocations are returned.
OHCI runs in the x86-64 VirtualBox image. Its hardware ED/TD prefix stays 16 bytes;
software links and cleanup pointers use native widths. Controller MMIO and IRQ
routing use the existing platform adapters. DMA buffers and descriptor pages
must fit below 4 GiB; inaccessible buffers fail submission without truncation.
There is no OHCI high-memory bounce-buffer support yet. Schedule allocation must
succeed before the controller enters the operational state.
A 6 GiB VirtualBox boot starts OHCI, resets its port and enumerates the configured
USB device (VID 80EE, PID 0030). At that stage, USB class-driver input/storage, UHCI, EHCI and xHCI
were not part of the long-mode boot. That established real control transfers,
not full USB feature parity. The boot harness requires successful enumeration as
well as the USB type/core/hub/OHCI test failure counters.
Validation after the OHCI changes: both target builds and VirtualBox boots pass.
The x86-64 runs at 64 MiB and 6 GiB report 55 USB type checks, 55 core checks,
44 hub checks and 91 OHCI checks with zero failures, plus real device enumeration.
The i386 boot reaches idle with the existing storage, USB/HID and core suites
passing. Original VM RAM and optical media are restored and the VM is off.
## USB class drivers and stable storage registration
The shared mass-storage, boot keyboard and boot mouse drivers now compile for
both targets through the platform adapters. The mouse receives bounds from the
video subsystem; i386 startup supplies the optional PS/2 keyboard-disable hook.
USB class registration stays in architecture startup composition.
Boot work after scheduler initialization runs in a normal process. Running it on
the idle context starved initialization once the persistent USB worker started.
Storage device records now have stable heap addresses behind native pointer
slots: registering a fifth disk previously moved the by-value registry and left
mounted volumes pointing at freed records. Registry publication and lookup exclude
interrupts. ISO9660 now stops on failed sector reads instead of parsing empty data.
VirtualBox checks pass at 64 MiB and 6 GiB: 40 mass-storage protocol tests, 62
keyboard tests and 33 mouse tests, plus the existing USB/core/OHCI and storage
suites. The existing USB disk serves a read-only sector-zero request through OHCI,
and the AHCI kernel-file read passes before and after USB registration. The 6 GiB
run also compares high-physical-memory reads against normal buffers. No USB writes
are used. The full i386 image builds and reaches idle with its suites passing.
Temporarily enabling VirtualBox USB keyboard and mouse binds both class drivers
alongside the disk. This validates attachment, not injected input: boot-protocol
requests returned failure and the existing drivers continued. Report delivery,
hot unplug, USB writes and UHCI/EHCI/xHCI remain unvalidated in long mode. The image now continues into the graphical desktop.
## Native desktop, networking and applications
The normal image runs the shared LVGL desktop and application manager. Both
architectures use the same application registrations; architecture startup retains
CPU/BIOS-specific commands. PS/2 mouse and keyboard drive the terminal, including
paced and burst input. Live BGA switching to 1280x800 and subsequent terminal input
pass in VirtualBox. The LVGL lock hands ownership to queued waiters, and framebuffer
flush stays inside that lock so mode changes cannot release a buffer during use.
E1000 uses native MMIO mappings, platform IRQ routing and owned DMA buffers.
VirtualBox NAT tests obtained a DHCP lease and received ping replies at 6 GiB;
DHCP also passed at 64 MiB. This does not establish complete TCP protocol coverage.
The WASM bridge resolves its context from the current process, initializes a
suspended process before publishing it, and releases partially loaded contexts on
failure. Native WASI proc_exit tests pass, and /disk/ram/hello prints Hello, World!
in the terminal. The external runtime's fixed VM stacks exceed the available RAM
in the 64 MiB configuration; launch is rejected before allocating those stacks.
MEMINFO uses platform physical-byte counters and reports RAM above 4 GiB.
Both target builds pass. The i386 image reaches idle with its suites reporting
zero failures. Native boots at 64 MiB and 6 GiB reach the interactive desktop;
the high-memory run also passes AHCI DMA comparisons above 4 GiB. MD5SUM of abc
matches 900150983CD24FB0D6963F7D28E17F72. VM test settings are restored afterward.
Full feature parity is still outstanding: UHCI/EHCI/xHCI, USB report delivery and
hot unplug, broader network workloads, and full interactive application coverage.
OHCI still rejects DMA addresses above its 32-bit hardware limit rather than
providing bounce buffers. These limits must not be described as a finished port.
Follow-up interactive checks pass with VirtualBox USB keyboard and mouse: the
mouse opens Terminal and paced/burst keyboard commands produce the expected
output. SET_PROTOCOL warnings remain, but report delivery is now demonstrated.
Files, Notepad and Disk Utility also open successfully; Files lists root entries,
and Disk Utility lists AHCI and USB devices. This checks startup and display,
not destructive disk operations or every editor/file-management workflow.
The application check exposed a duplicate core.strings.helpers unit shadowing
the native implementation. Removing the stale copy fixes the Files sorting fault
without changing compiler search rules. Low-memory WASM launch now displays the
handler's memory error, and a subsequent terminal command succeeds.