# Volt Phase 3 — SMP Support Results **Date:** 2026-03-09 **Status:** ✅ Complete — All success criteria met ## Summary Implemented Intel MultiProcessor Specification (MPS v1.4) tables for Volt VMM, enabling guest kernels to discover and boot multiple vCPUs. VMs with 1, 2, and 4 vCPUs all boot successfully with the kernel reporting the correct number of processors. ## What Was Implemented ### 1. MP Table Construction (`vmm/src/boot/mptable.rs`) — NEW FILE Created a complete MP table builder that writes Intel MPS-compliant structures to guest memory at address `0x9FC00` (just below EBDA, a conventional location Linux scans during boot). **Table Layout:** ``` 0x9FC00: MP Floating Pointer Structure (16 bytes) - Signature: "_MP_" - Pointer to MP Config Table (0x9FC10) - Spec revision: 1.4 - Feature byte 2: IMCR present (0x80) - Two's-complement checksum 0x9FC10: MP Configuration Table Header (44 bytes) - Signature: "PCMP" - OEM ID: "NOVAFLAR" - Product ID: "VOLT VM" - Local APIC address: 0xFEE00000 - Entry count, checksum 0x9FC3C+: Processor Entries (20 bytes each) - CPU 0: APIC ID=0, flags=EN|BP (Bootstrap Processor) - CPU 1: APIC ID=1, flags=EN (Application Processor) - CPU N: APIC ID=N, flags=EN - CPU signature: Family 6, Model 15, Stepping 1 - Local APIC version: 0x14 (integrated) After processors: Bus Entry (8 bytes) - Bus ID=0, Type="ISA " After bus: I/O APIC Entry (8 bytes) - ID=num_cpus (first unused APIC ID) - Version: 0x11 - Address: 0xFEC00000 After I/O APIC: 16 I/O Interrupt Entries (8 bytes each) - IRQ 0: ExtINT → IOAPIC pin 0 - IRQs 1-15: INT → IOAPIC pins 1-15 ``` **Total sizes:** - 1 CPU: 224 bytes (19 entries) - 2 CPUs: 244 bytes (20 entries) - 4 CPUs: 284 bytes (22 entries) All fit comfortably in the 1024-byte space between 0x9FC00 and 0xA0000. ### 2. Boot Module Integration (`vmm/src/boot/mod.rs`) - Registered `mptable` module - Exported `setup_mptable` function ### 3. Main VMM Integration (`vmm/src/main.rs`) - Added `setup_mptable()` call in `load_kernel()` after `BootLoader::setup()` completes - MP tables are written to guest memory before vCPU creation - Works for any vCPU count (1-255) ### 4. CPUID Topology Updates (`vmm/src/kvm/cpuid.rs`) - **Leaf 0x1 (Feature Info):** HTT bit (EDX bit 28) is now enabled when vcpu_count > 1, telling the kernel to parse APIC topology - **Leaf 0x1 EBX:** Initial APIC ID set per-vCPU, logical processor count set to vcpu_count - **Leaf 0xB (Extended Topology):** Properly reports SMT and Core topology levels: - Subleaf 0 (SMT): 1 thread per core, level type = SMT - Subleaf 1 (Core): N cores per package, level type = Core, correct bit shift for APIC ID - Subleaf 2+: Invalid (terminates enumeration) - **Leaf 0x4 (Cache Topology):** Reports correct max cores per package ## Test Results ### Build ``` ✅ cargo build --release — 0 errors, 0 warnings ✅ cargo test --lib boot::mptable — 11/11 tests passed ``` ### VM Boot Tests | Test | vCPUs | Kernel Reports | Status | |------|-------|---------------|--------| | 1 CPU | `--cpus 1` | `Processors: 1`, `nr_cpu_ids:1` | ✅ Pass | | 2 CPUs | `--cpus 2` | `Processors: 2`, `Brought up 1 node, 2 CPUs` | ✅ Pass | | 4 CPUs | `--cpus 4` | `Processors: 4`, `Brought up 1 node, 4 CPUs`, `Total of 4 processors activated` | ✅ Pass | ### Key Kernel Log Lines (4 CPU test) ``` found SMP MP-table at [mem 0x0009fc00-0x0009fc0f] Intel MultiProcessor Specification v1.4 MPTABLE: OEM ID: NOVAFLAR MPTABLE: Product ID: VOLT VM MPTABLE: APIC at: 0xFEE00000 Processor #0 (Bootup-CPU) Processor #1 Processor #2 Processor #3 IOAPIC[0]: apic_id 4, version 17, address 0xfec00000, GSI 0-23 Processors: 4 smpboot: Allowing 4 CPUs, 0 hotplug CPUs ... smp: Bringing up secondary CPUs ... x86: Booting SMP configuration: .... node #0, CPUs: #1 smp: Brought up 1 node, 4 CPUs smpboot: Total of 4 processors activated (19154.99 BogoMIPS) ``` ## Unit Tests 11 tests in `vmm/src/boot/mptable.rs`: | Test | Description | |------|-------------| | `test_checksum` | Verifies two's-complement checksum arithmetic | | `test_mp_floating_pointer_signature` | Checks "_MP_" signature at correct address | | `test_mp_floating_pointer_checksum` | Validates FP structure checksum = 0 | | `test_mp_config_table_checksum` | Validates config table checksum = 0 | | `test_mp_config_table_signature` | Checks "PCMP" signature | | `test_mp_table_1_cpu` | 1 CPU: 19 entries (1 proc + bus + IOAPIC + 16 IRQs) | | `test_mp_table_4_cpus` | 4 CPUs: 22 entries | | `test_mp_table_bsp_flag` | CPU 0 has BSP+EN flags, CPU 1 has EN only | | `test_mp_table_ioapic` | IOAPIC ID and address are correct | | `test_mp_table_zero_cpus_error` | 0 CPUs correctly returns error | | `test_mp_table_local_apic_addr` | Local APIC address = 0xFEE00000 | ## Files Modified | File | Change | |------|--------| | `vmm/src/boot/mptable.rs` | **NEW** — MP table construction (340 lines) | | `vmm/src/boot/mod.rs` | Added `mptable` module and `setup_mptable` export | | `vmm/src/main.rs` | Added `setup_mptable()` call after boot loader setup | | `vmm/src/kvm/cpuid.rs` | Fixed HTT bit, enhanced leaf 0xB topology reporting | ## Architecture Notes ### Why MP Tables (not ACPI MADT)? MP tables are simpler (Intel MPS v1.4 is ~400 bytes of structures) and universally supported by Linux kernels from 2.6 onwards. ACPI MADT would require implementing RSDP, RSDT/XSDT, and MADT — significantly more complexity for no benefit with the kernel versions we target. The 4.14 kernel used in testing immediately found and parsed the MP tables: ``` found SMP MP-table at [mem 0x0009fc00-0x0009fc0f] ``` ### Integration Point MP tables are written in `Vmm::load_kernel()` immediately after `BootLoader::setup()` completes. This ensures: 1. Guest memory is already allocated and mapped 2. E820 memory map is already configured (including EBDA reservation at 0x9FC00) 3. The MP table address doesn't conflict with page tables (0x1000-0xA000) or boot params (0x20000+) ### CPUID Topology The HTT bit in CPUID leaf 0x1 EDX is critical — without it, some kernels skip AP startup entirely because they believe the system is uniprocessor regardless of MP table content. We now enable it for multi-vCPU VMs. ## Future Work - **ACPI MADT:** For newer kernels (5.x+) that prefer ACPI, add RSDP/RSDT/MADT tables - **CPU hotplug:** MP tables are static; ACPI would enable runtime CPU add/remove - **NUMA topology:** For large VMs, SRAT/SLIT tables could improve memory locality