Skip to content

feat: Fix acpi and cpuid - #179

Merged
junyu0312 merged 2 commits into
mainfrom
dev
Jun 19, 2026
Merged

junyu0312 merged 2 commits into
mainfrom
dev

Conversation

@junyu0312

@junyu0312 junyu0312 commented Jun 19, 2026 •

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • Refactor

    • Improved x86_64 virtual CPU CPUID configuration handling with enhanced ID-based updates.
    • Updated device port allocation logic for consistency.
    • Enhanced ACPI firmware configuration with standardized flag definitions replacing hardcoded values.
  • Bug Fixes

    • Added error handling for oversized virtual CPU identifiers during CPUID setup.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Three independent improvements: KVM vCPU CPUID initialization gains a new cpu_id submodule that patches the INITIAL_APIC_ID field in leaf 0x01 per-vCPU; the dummy PIO device switches its reserved port range to 0x87; and ACPI FADT flags are set from named bitmask constants instead of a hardcoded zero.

Changes

KVM vCPU CPUID per-vCPU APIC ID

Layer / File(s) Summary
update_cpuid helper, error variant, and KvmVcpu::new integration
crates/vm-core/src/virtualization/vcpu/error.rs, crates/vm-core/src/virtualization/kvm/vcpu/cpu_id.rs, crates/vm-core/src/virtualization/kvm/vcpu.rs
VcpuError gains UpdateCpuid(&'static str). update_cpuid clones CpuId, masks ebx in leaf 0x01, and writes vcpu_id as INITIAL_APIC_ID. KvmVcpu::new replaces the direct set_cpuid2 call with update_cpuid → set_cpuid2, returning UpdateCpuid on vcpu_id conversion failure.

Dummy PIO device port range update

Layer / File(s) Summary
Dummy PIO port reservation and ports() return value
crates/vm-device/src/device/dummy.rs
Dummy::new reserves 0x87 instead of 0x1004/0x1006 from RangeAllocator, and Dummy::ports returns a single 0x87..0x88 range.

ACPI FADT flags constants

Layer / File(s) Summary
FADT bitmask constants and Fadt::new flags initialization
crates/vm-firmware/src/acpi/type/fadt.rs
Three const bitmasks (power button, sleep button, hardware-reduced ACPI) are defined and OR-ed to set Fadt::flags; prior explicit zero-value TODO fields are removed in favor of ..Default::default().

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop! The APIC IDs align,
Each vCPU knows its number is mine!
Port 0x87 gets a home in the list,
FADT's flags no longer resist.
Named bitmasks bloom where zeros once lay—
A tidier VM hops into the day! 🌸

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'feat: Fix acpi and cpuid' is vague and generic, using only high-level component names without specifying what fixes are being applied or what problems are being solved. Consider a more descriptive title such as 'feat: Add CPUID updates for vCPU IDs and ACPI FADT configuration' to clarify the specific changes and improvements being made.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
crates/vm-device/src/device/dummy.rs (1)

12-12: ⚡ Quick win

Deduplicate the dummy PIO port definition to avoid contract drift.

0x87 is hardcoded in both Dummy::new and ports(). Define a shared constant so reservation and advertised ports cannot diverge in a later edit.

Proposed diff
+const DUMMY_PIO_PORT: u16 = 0x87;
+const DUMMY_PIO_LEN: usize = 1;
+
 impl Dummy {
     pub fn new(pio_allocator: &mut RangeAllocator<u16>) -> Result<Self, DeviceError> {
-        let _ = pio_allocator.reserve(0x87, 1)?;
+        let _ = pio_allocator.reserve(DUMMY_PIO_PORT, DUMMY_PIO_LEN)?;
 
         Ok(Dummy)
     }
 }
 
 impl PioDevice for Dummy {
     fn ports(&self) -> Vec<Range<u16>> {
-        let range = 0x87..0x88;
+        let range = DUMMY_PIO_PORT..(DUMMY_PIO_PORT + DUMMY_PIO_LEN as u16);
 
         vec![
             // TODO: What's this
             range,
         ]
     }

Also applies to: 34-39

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/vm-device/src/device/dummy.rs` at line 12, The port number 0x87 is
hardcoded in two locations: in the Dummy::new method where it is reserved via
pio_allocator.reserve, and in the ports method where the supported ports are
advertised. To prevent these definitions from diverging, define a shared
constant at the module level or in an appropriate scope for this port number,
then replace both hardcoded instances of 0x87 with references to this constant
in both the reserve call and the ports method return value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/vm-core/src/virtualization/kvm/vcpu.rs`:
- Around line 65-70: Add upstream validation in the VmConfig to enforce the u8
vCPU-ID cap before vCPU creation occurs. The current code in the update_cpuid
call relies on a try_into conversion that fails at vCPU creation time if vcpu_id
exceeds 255, but VmConfig::vcpus has no validation to prevent this. Add a
validation check when VmConfig is created or validated to ensure vcpus does not
exceed 256 (the maximum value representable in u8), providing a clear
configuration-level error message rather than a runtime error during vCPU
creation.

---

Nitpick comments:
In `@crates/vm-device/src/device/dummy.rs`:
- Line 12: The port number 0x87 is hardcoded in two locations: in the Dummy::new
method where it is reserved via pio_allocator.reserve, and in the ports method
where the supported ports are advertised. To prevent these definitions from
diverging, define a shared constant at the module level or in an appropriate
scope for this port number, then replace both hardcoded instances of 0x87 with
references to this constant in both the reserve call and the ports method return
value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 16c6a68d-669d-4daa-af45-9912e3ebafd4

📥 Commits

Reviewing files that changed from the base of the PR and between cfca91f and f7146e3.

📒 Files selected for processing (5)
  • crates/vm-core/src/virtualization/kvm/vcpu.rs
  • crates/vm-core/src/virtualization/kvm/vcpu/cpu_id.rs
  • crates/vm-core/src/virtualization/vcpu/error.rs
  • crates/vm-device/src/device/dummy.rs
  • crates/vm-firmware/src/acpi/type/fadt.rs

Comment on lines +65 to +70
let cpuid = update_cpuid(
supported_cpuid,
vcpu_id
.try_into()
.map_err(|_| VcpuError::UpdateCpuid("vcpu_id too large"))?,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== KvmVcpu::new call sites =="
rg -nP -C3 '\bKvmVcpu::new\s*\(' --type rust

echo
echo "== vCPU count/id config symbols =="
rg -nP -C3 '\b(vcpu_id|vcpu_count|max_vcpus|num_vcpus|cpu_count)\b' --type rust

echo
echo "== Existing upper-bound checks related to 255/u8::MAX =="
rg -nP -C3 '\b(255|u8::MAX)\b' --type rust

echo
echo "== Other narrowing conversions on vcpu_id =="
rg -nP -C3 '\bvcpu_id\b.*\btry_into\s*\(|\bvcpu_id\b.*\bas\s*u8\b' --type rust

Repository: junyu0312/rust-vm

Length of output: 29867


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== VmConfig definition and vcpus field =="
rg -nP 'struct\s+VmConfig|vcpus\s*:' --type rust -B2 -A5

echo
echo "== Config validation logic =="
rg -nP 'validate|check.*vcpu|max.*vcpu' --type rust -B2 -A2

echo
echo "== Machine config or startup validation =="
fd -e rs -e toml | xargs rg -l 'max.*vcpu|validate.*config|vcpu.*limit' 2>/dev/null | head -5

echo
echo "== KVM create_vcpu constraints (to understand the u64 parameter) =="
rg -nP 'create_vcpu' --type rust -B1 -A3

Repository: junyu0312/rust-vm

Length of output: 9022


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== ACPI set_vcpus usage =="
rg -nP 'set_vcpus|\.vcpus' --type rust -B3 -A3

echo
echo "== x86_64 bootloader ACPI setup =="
cat -n crates/vm-bootloader/src/boot_loader/arch/x86_64.rs | sed -n '50,100p'

echo
echo "== Where ACPI is built for x86_64 =="
rg -nP 'AcpiTableBuilder|setup_acpi' --type rust -B2 -A5

Repository: junyu0312/rust-vm

Length of output: 18220


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Aarch64 bootloader load function (full) =="
cat -n crates/vm-bootloader/src/boot_loader/arch/aarch64.rs | sed -n '60,130p'

echo
echo "== Error types for vCPU validation =="
rg -nP 'VcpuExceedsAcpiCapability|VcpuError|enum.*Error' --type rust -B1 -A3 | head -60

Repository: junyu0312/rust-vm

Length of output: 6317


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== VM initialization order: bootloader vs vcpu creation =="
cat -n crates/vm-vmm/src/vm/config.rs | sed -n '90,140p'

echo
echo "== Bootloader load error path =="
rg -nP 'bootloader.*load|load.*bootloader' --type rust -B2 -A5

echo
echo "== Check if bootloader failure prevents vcpu creation =="
rg -nP 'bootloader|vcpu_manager' --type rust crates/vm-vmm/src/vm/config.rs -B1 -A1

Repository: junyu0312/rust-vm

Length of output: 7111


Confirm the new u8 vCPU-ID cap is enforced upstream.

This introduces a hard failure for vcpu_id >= 256. vCPU creation (lines 67-69) has no upstream validation—VmConfig::vcpus is unchecked and passed directly to the vCPU creation loop. For x86_64, the bootloader does validate vcpus after vCPU creation (redundant), and aarch64 has no validation outside this try_into. Consider adding config-level validation to fail earlier with a clearer error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/vm-core/src/virtualization/kvm/vcpu.rs` around lines 65 - 70, Add
upstream validation in the VmConfig to enforce the u8 vCPU-ID cap before vCPU
creation occurs. The current code in the update_cpuid call relies on a try_into
conversion that fails at vCPU creation time if vcpu_id exceeds 255, but
VmConfig::vcpus has no validation to prevent this. Add a validation check when
VmConfig is created or validated to ensure vcpus does not exceed 256 (the
maximum value representable in u8), providing a clear configuration-level error
message rather than a runtime error during vCPU creation.

@junyu0312
junyu0312 merged commit 1173dca into main Jun 19, 2026
12 checks passed
@junyu0312
junyu0312 deleted the dev branch June 21, 2026 19:00
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