Repository navigation
fix(x86_64): find the IRQs of virtio-mmio devices on QEMU microvm with ACPI - #2777
Merged
Merged
Conversation
There was a problem hiding this comment.
Benchmark Results
Details
| Benchmark | Current: ec8716a | Previous: 2e23902 | Performance Ratio |
|---|---|---|---|
| startup_benchmark Build Time | 90.85 s |
80.34 s |
1.13 ❗ |
| startup_benchmark File Size | 0.80 MB |
0.80 MB |
1.00 ❗ |
| Startup Time - 1 core | 0.75 s (±0.01 s) |
0.75 s (±0.02 s) |
1.01 |
| Startup Time - 2 cores | 0.75 s (±0.02 s) |
0.74 s (±0.02 s) |
1.01 |
| Startup Time - 4 cores | 0.75 s (±0.02 s) |
0.74 s (±0.02 s) |
1.01 |
| multithreaded_benchmark Build Time | 90.91 s |
82.11 s |
1.11 ❗ |
| multithreaded_benchmark File Size | 0.89 MB |
0.86 MB |
1.04 ❗ |
| Multithreaded Pi Efficiency - 2 Threads | 89.60 % (±8.21 %) |
85.89 % (±6.61 %) |
1.04 |
| Multithreaded Pi Efficiency - 4 Threads | 45.17 % (±2.66 %) |
43.43 % (±2.56 %) |
1.04 |
| Multithreaded Pi Efficiency - 8 Threads | 26.24 % (±1.69 %) |
25.76 % (±1.53 %) |
1.02 |
| micro_benchmarks Build Time | 89.62 s |
80.40 s |
1.11 ❗ |
| micro_benchmarks File Size | 0.89 MB |
0.86 MB |
1.04 ❗ |
| Scheduling time - 1 thread | 68.03 ticks (±2.18 ticks) |
62.65 ticks (±4.06 ticks) |
1.09 ❗ |
| Scheduling time - 2 threads | 37.60 ticks (±4.22 ticks) |
34.08 ticks (±4.10 ticks) |
1.10 |
| Micro - Time for syscall (getpid) | 3.56 ticks (±0.61 ticks) |
3.45 ticks (±0.58 ticks) |
1.03 |
| Memcpy speed - (built_in) block size 4096 | 80102.15 MByte/s (±55565.32 MByte/s) |
82448.38 MByte/s (±56997.13 MByte/s) |
0.97 |
| Memcpy speed - (built_in) block size 1048576 | 30119.46 MByte/s (±24412.89 MByte/s) |
30585.98 MByte/s (±24707.84 MByte/s) |
0.98 |
| Memcpy speed - (built_in) block size 16777216 | 25904.73 MByte/s (±21446.54 MByte/s) |
26340.06 MByte/s (±21720.96 MByte/s) |
0.98 |
| Memset speed - (built_in) block size 4096 | 80660.25 MByte/s (±55918.38 MByte/s) |
82292.76 MByte/s (±56891.50 MByte/s) |
0.98 |
| Memset speed - (built_in) block size 1048576 | 30798.10 MByte/s (±24811.49 MByte/s) |
31323.85 MByte/s (±25145.86 MByte/s) |
0.98 |
| Memset speed - (built_in) block size 16777216 | 26591.01 MByte/s (±21853.16 MByte/s) |
27104.68 MByte/s (±22209.94 MByte/s) |
0.98 |
| Memcpy speed - (rust) block size 4096 | 72867.95 MByte/s (±51085.29 MByte/s) |
74097.96 MByte/s (±51811.44 MByte/s) |
0.98 |
| Memcpy speed - (rust) block size 1048576 | 29789.86 MByte/s (±24275.06 MByte/s) |
30361.60 MByte/s (±24602.37 MByte/s) |
0.98 |
| Memcpy speed - (rust) block size 16777216 | 25480.44 MByte/s (±21197.49 MByte/s) |
27625.34 MByte/s (±22806.88 MByte/s) |
0.92 |
| Memset speed - (rust) block size 4096 | 73042.78 MByte/s (±51199.32 MByte/s) |
74373.47 MByte/s (±51976.48 MByte/s) |
0.98 |
| Memset speed - (rust) block size 1048576 | 30506.73 MByte/s (±24677.12 MByte/s) |
31110.89 MByte/s (±25033.24 MByte/s) |
0.98 |
| Memset speed - (rust) block size 16777216 | 26167.62 MByte/s (±21610.22 MByte/s) |
28386.93 MByte/s (±23265.03 MByte/s) |
0.92 |
| alloc_benchmarks Build Time | 82.61 s |
74.76 s |
1.11 ❗ |
| alloc_benchmarks File Size | 0.87 MB |
0.87 MB |
1.00 ❗ |
| Allocations - Allocation success | 91.35 % |
91.31 % |
1.00 ❗ |
| Allocations - Deallocation success | 100.00 % |
100.00 % |
1 |
| Allocations - Pre-fail Allocations | 61.61 % |
61.44 % |
1.00 ❗ |
| Allocations - Average Allocation time | 9214.02 Ticks (±87.52 Ticks) |
5860.58 Ticks (±98.43 Ticks) |
1.57 ❗ |
| Allocations - Average Allocation time (no fail) | 9628.61 Ticks (±94.32 Ticks) |
6554.81 Ticks (±92.86 Ticks) |
1.47 ❗ |
| Allocations - Average Deallocation time | 1388.79 Ticks (±338.16 Ticks) |
1805.01 Ticks (±250.35 Ticks) |
0.77 |
| mutex_benchmark Build Time | 82.56 s |
79.82 s |
1.03 ❗ |
| mutex_benchmark File Size | 0.89 MB |
0.86 MB |
1.04 ❗ |
| Mutex Stress Test Average Time per Iteration - 1 Threads | 12.26 ns (±0.48 ns) |
12.10 ns (±0.41 ns) |
1.01 |
| Mutex Stress Test Average Time per Iteration - 2 Threads | 93.70 ns (±6.51 ns) |
40.26 ns (±1.68 ns) |
2.33 ❗ |
This comment was automatically generated by workflow using github-action-benchmark.
martijnhoekstra
force-pushed
the
fix/microvm-mmio-irq
branch
from
November 7, 2026 13:01
072d694 to
93b65bf
Compare
Contributor
|
@martijnhoekstra Can you rebase your PR and test it? |
The IOAPIC routes GSI n to vector 32 + n, but only IRQs 0 to 15 went to handle_interrupt. Any other IRQ hit the exception handler, which stops the core. On QEMU's microvm with ioapic2=off, the virtio-mmio NIC raises IRQ 23, and Hermit stops with "Exception 55" before the application starts. Send IRQs 0 to 79 to handle_interrupt. The vectors from 112 up stay with the local APIC. Assisted-by: Claude:claude-opus-5-5
martijnhoekstra
force-pushed
the
fix/microvm-mmio-irq
branch
from
November 7, 2026 17:34
1552057 to
2c6b732
Compare
Without virtio_mmio.device= arguments, Hermit probes QEMU microvm's transports and assumes transport n uses IRQ 5 + n. That only holds with acpi=off. With ACPI, QEMU uses other GSIs and describes each transport in the DSDT as an LNRO0005 device. Read those devices with the acpi crate's AML interpreter. Probe only if there are no ACPI tables. Assisted-by: Claude:claude-opus-5-5
martijnhoekstra
force-pushed
the
fix/microvm-mmio-irq
branch
from
November 7, 2026 18:47
2c6b732 to
ec8716a
Compare
Contributor
Author
|
Rebased onto main and retested. With #2770, #2771 and #2775 on main, |
stlankes
self-requested a review
November 7, 2026 22:47
stlankes
approved these changes
Nov 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2776. Hermit's CI boots
microvmwithacpi=off, where this already works. The issue also describes taking only the first commit.Without
virtio_mmio.device=arguments, Hermit probes QEMU microvm's virtio-mmio transports and assumes transport n uses IRQ 5 + n. QEMU only numbers them that way withacpi=off. With ACPI andioapic2=off, transport n uses GSI 16 + n. With the second IOAPIC, the default, there are 24 transports on GSIs 24 to 47. With ACPI on, QEMU puts nothing on the command line. Only the DSDT says which GSI each transport uses: each one is anLNRO0005device with a memory range and an interrupt.With
-machine microvm,ioapic2=off, the NIC is transport 7 at 0xfeb00e00 and raises GSI 23, but Hermit installs its handler on IRQ 12. The interrupt arrives at vector 55. Hermit only sends IRQs 0 to 15 tohandle_interrupt, so vector 55 goes to the exception handler, and the core stops before the application starts:Two commits:
handle_interrupt. The vectors from 112 up stay with the local APIC.handle_interruptalready acknowledges and counts an IRQ that has no handler.LNRO0005devices, and takes the address and interrupt from their_CRS. It only probes the fixed layout if there are no ACPI tables, as withacpi=off. On machines whose ACPI tables list no virtio-mmio devices, it no longer reads the microvm addresses. This links the AML interpreter into x86_64 builds withacpiand withoutpci. The echo application below grew by 227 KB.Tested on main with
hermit-loader-x86_64-multibootv0.5.7 and a TCP and UDP echo application built withoutpci, in QEMU 7.2:microvmwith default options, under KVM and TCG: Hermit finds the NIC at 0xfeb02e00 on GSI 47, and the echo test passes.microvm,ioapic2=off(KVM): Hermit installs the handler on IRQ 23, and the echo test passes.microvm,acpi=off(KVM): probing still finds the NIC on IRQ 12, and the echo test passes.pci: Hermit boots and finds no network device, as on main, but no longer probes the 8 microvm addresses.cargo test --lib, the integration tests and clippy (x86_64, aarch64, riscv64, and x86_64 withoutpci, with and withoutacpi) pass.The DSDT describes the virtio-mmio interrupts as level-triggered and active high, but Hermit still programs every IOAPIC line edge-triggered, as before. That works on QEMU's IOAPIC under both KVM and TCG. I haven't changed the trigger mode.