Volt VMM (Neutron Stardust): source-available under AGPSL v5.0

KVM-based microVMM for the Volt platform:
- Sub-second VM boot times
- Minimal memory footprint
- Landlock LSM + seccomp security
- Virtio device support
- Custom kernel management

Copyright (c) Armored Gates LLC. All rights reserved.
Licensed under AGPSL v5.0
This commit is contained in:
Karl Clinger
2026-03-21 01:04:35 -05:00
commit 40ed108dd5
143 changed files with 50300 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
# i8042 PS/2 Controller Implementation
## Summary
Completed the i8042 PS/2 keyboard controller emulation to handle the full Linux
kernel probe sequence. Previously, the controller only handled self-test (0xAA)
and interface test (0xAB), but was missing the command byte (CTR) read/write
support, causing the kernel to fail with "Can't read CTR while initializing
i8042" and adding ~500ms+ of timeout penalty during boot.
## Problem
The Linux kernel's i8042 driver probe sequence requires:
1. **Self-test** (0xAA → 0x55) ✅ was working
2. **Read CTR** (0x20 → command byte on port 0x60) ❌ was missing
3. **Write CTR** (0x60, then data byte to port 0x60) ❌ was missing
4. **Interface test** (0xAB → 0x00) ✅ was working
5. **Enable/disable keyboard** (0xAD/0xAE) ❌ was missing
Additionally, the code had compilation errors — `I8042State` in `vcpu.rs`
referenced `self.cmd_byte` and `self.expecting_data` fields that didn't exist
in the struct definition. The data port (0x60) write handler also didn't forward
writes to the i8042 state machine.
## Changes Made
### `vmm/src/kvm/vcpu.rs` — Active I8042State (used in vCPU run loop)
Added missing fields to `I8042State`:
- `cmd_byte: u8` — Controller Configuration Register, default `0x47`
(keyboard IRQ enabled, system flag, keyboard enabled, translation)
- `expecting_data: bool` — tracks when next port 0x60 write is a command data byte
- `pending_cmd: u8` — which command is waiting for data
Added `write_data()` method for port 0x60 writes:
- Handles 0x60 (write command byte) data phase
- Handles 0xD4 (write to aux device) data phase
Enhanced `write_command()`:
- 0x20: Read command byte → queues `cmd_byte` to output buffer
- 0x60: Write command byte → sets `expecting_data`, `pending_cmd`
- 0xA7/0xA8: Disable/enable aux port (updates CTR bit 5)
- 0xA9: Aux interface test → queues 0x00
- 0xAA: Self-test → queues 0x55, resets CTR to default
- 0xAD/0xAE: Disable/enable keyboard (updates CTR bit 4)
- 0xD4: Write to aux → sets `expecting_data`, `pending_cmd`
Fixed port 0x60 IoOut handler to call `i8042.write_data(data[0])` instead of
ignoring all data port writes.
### `vmm/src/devices/i8042.rs` — Library I8042 (updated for parity)
Rewrote to match the same logic as the vcpu.rs inline version, with full
test coverage including the complete Linux probe sequence test.
## Boot Timing Results (5 iterations)
Kernel: vmlinux (4.14.174), Memory: 128M, Command line includes `i8042.noaux`
| Run | i8042 Init (kernel time) | KBD Port Ready | Reboot Trigger |
|-----|--------------------------|----------------|----------------|
| 1 | 0.288149s | 0.288716s | 1.118453s |
| 2 | 0.287622s | 0.288232s | 1.116971s |
| 3 | 0.292594s | 0.293164s | 1.123013s |
| 4 | 0.288518s | 0.289095s | 1.118687s |
| 5 | 0.288203s | 0.288780s | 1.119400s |
**Average i8042 init time: 0.289s** (kernel timestamp)
**i8042 init duration: <1ms** (from "Keylock active" to "KBD port" message)
### Before Fix
The kernel would output:
```
i8042: Can't read CTR while initializing i8042
```
and the i8042 probe would either timeout (~500ms-1000ms penalty) or fail entirely,
depending on kernel configuration. The `i8042.noaux` kernel parameter mitigates
some of the timeout but the CTR read failure still caused delays.
### After Fix
The kernel successfully probes the i8042:
```
[ 0.288149] i8042: Warning: Keylock active
[ 0.288716] serio: i8042 KBD port at 0x60,0x64 irq 1
```
The "Warning: Keylock active" message is normal — it's because our default CTR
value (0x47) has bit 2 (system flag) set, which the kernel interprets as the
keylock being active. This is harmless.
## Status Register (OBF) Behavior
The status register (port 0x64 read) correctly reflects the Output Buffer Full
(OBF) bit:
- **OBF set (bit 0 = 1)**: When the output queue has data pending for the guest
to read from port 0x60 (after self-test, read CTR, interface test, etc.)
- **OBF clear (bit 0 = 0)**: When the output queue is empty (after the guest
reads all pending data from port 0x60)
This is critical because the Linux kernel polls the status register to know when
response data is available. Without correct OBF tracking, the kernel's
`i8042_wait_read()` times out.
## Architecture Note
There are two i8042 implementations in the codebase:
1. **`vmm/src/kvm/vcpu.rs`** — Inline `I8042State` struct used in the actual vCPU
run loop. This is the active implementation.
2. **`vmm/src/devices/i8042.rs`** — Library `I8042` struct with full test suite.
This is exported but currently unused in the hot path.
Both are kept in sync. A future refactor could consolidate them by having the
vCPU run loop use the `devices::I8042` implementation directly.