Was ASPM macht

PCIe Active State Power Management (ASPM) erlaubt PCIe-Links, in Zustände mit geringer Leistung zu gehen, wenn sie unbeschäftigt sind. Die PCIe-Spezifikation legt mehrere Link-Zustände fest:

L0 ist der voll aktive Zustand. Der Link steht, beide Enden sind versorgt, Daten können sofort fließen.

L0s ist ein leichter Ruhezustand. Der Link fährt teilweise herunter. Die Rückkehr nach L0 dauert je nach Hardware etwa 1–4 µs. Beide Enden können unabhängig voneinander in L0s gehen.

L1 ist ein tieferer Ruhezustand. Beide Enden des Links fahren gemeinsam herunter. Die Rückkehr nach L0 dauert länger — typisch 2–32 µs, manchmal mehr. Die genaue Rückkehrzeit hängt vom Gerät, der PCIe-Generation und der Plattform ab.

L1.1 und L1.2 sind Unterzustände von L1, eingeführt mit PCIe 3.0. Sie senken die Leistung weiter, indem sie die PLL-Taktreferenz abschalten. Die Rückkehr aus L1.2 kann 32–100 µs dauern. Für ein Speichergerät ist das kein Rundungsfehler. Das ist etwa so lang wie der Lesezugriff, den du überhaupt machen wolltest.

Je tiefer der Link schläft, desto länger wartet das nächste IOLink-ZustandRückkehrzeit nach L0 — die Latenz, die ein IO zahlt, wenn es jetzt eintrifftL0voll aktiv — Daten fließen sofortkeineL0sleichte Ruhe, jedes Ende für sich1–4 µsL1tiefe Ruhe, beide Enden zusammen2–32 µsL1.1 / L1.2PCIe-3.0-Unterzustände — PLL-Takt aus32–100 µsBalken maßstäblich gegen den schlimmsten Fall von 100 µs. Tieferer Schlaf spart mehr Leistung und kostet mehr beim Aufwachen.
Die Balken sind die Rückkehrzeiten, maßstäblich gegen den schlimmsten Fall von 100 µs gezeichnet. Tieferer Schlaf spart mehr Leistung und kostet mehr, wenn der Verkehr wieder anläuft.

Die Idee ist geradeheraus. Ist ein PCIe-Link ein paar Mikrosekunden unbeschäftigt, versetze ihn in einen Zustand mit geringerer Leistung. Läuft der Verkehr wieder an, wecke ihn auf. Spare in der Zwischenzeit ein wenig Strom.

Auf einem Laptop oder einem Desktop, der die meiste Zeit nichts tut, spart ASPM echten Strom. Ein paar Watt pro Link, aufsummiert über alle PCIe-Geräte im System. Auf einem Server mit IO-lastiger Arbeit sind die Links selten lang genug unbeschäftigt, dass ASPM sinnvoll greift.

Warum es beim Passthrough Probleme macht

Auf Blech verhandeln das Betriebssystem und der Gerätetreiber die Energieverwaltung miteinander. Der NVMe-Treiber weiß, wann der Link gleich unbeschäftigt wird und wann er gleich neues IO abschickt. Das PCIe-Subsystem des Kernels stimmt die Wechsel der Link-Zustände mit dem Treiber ab. Alles läuft im Gleichtakt.

Unter VFIO-Passthrough bricht diese Abstimmung zusammen.

Der Host-Kernel steuert weiterhin den physischen PCIe-Link. Die Gast-VM besitzt das Gerät über VFIO, aber sie steuert den Link selbst nicht. Das PCIe-Subsystem des Hosts sieht den Link unbeschäftigt werden — denn aus Sicht des Hosts nutzt ihn kein Treiber auf der Host-Seite. Es versetzt den Link in einen Zustand mit geringer Leistung. Wenn der Gast IO abschickt, braucht das Gerät den Link zurück in L0. Die Rückkehrzeit taucht als zusätzliche Latenz auf dieser IO-Operation auf.

Das Ergebnis ist ungleichmäßige Latenz. Die meisten IOs werden mit normaler Geschwindigkeit fertig. Manche brauchen viel länger, weil sie auf einen Link treffen, der in L1 oder L1.2 liegt und erst aufwachen muss. Das zeigt sich als weite Streuung in deinen clat-Perzentilen (Completion Latency). Der Durchschnitt sieht vielleicht in Ordnung aus. Das p99 ist vielleicht 5- bis 10-mal höher.

Das ist schwer zu erkennen, weil die Zahlen für den Durchsatz in Ordnung aussehen können. Du siehst das Problem nur, wenn du auf die Latenz am Ausläufer schaust. Viele Benchmarks heben sie nicht hervor, solange du keine Perzentile anforderst.

ASPM lässt den Durchschnitt unberührt und zerstört den AusläuferASPM anpcie_aspm=offCompletion-Latenz (µs)03060901203× schlechter bei p99 — und 7× der eigene DurchschnittASPM anpcie_aspm=offp50p90p99p99.9p99.99Durchschnitt und p50 sind in beiden Durchläufen identisch — nur der Ausläufer trennt sie.Die Zahlen zeigen das Muster, sie sind keine Messungen an einem bestimmten Laufwerk.
Dasselbe Laufwerk mit und ohne ASPM. p50 ist identisch, ein Benchmark, der nur den Durchschnitt zeigt, meldet also überhaupt kein Problem; der Schaden liegt komplett hinter p90, wo sich die IOs sammeln, die auf einen schlafenden Link getroffen sind.

Der VFIO-eigene Haken

Es gibt hier einen Haken, der über das einfache Problem „Host und Gast streiten um den Link-Zustand“ hinausgeht.

Ist ein Gerät auf dem Host an vfio-pci gebunden, weiß der Host-Kernel, dass das Gerät im Passthrough-Modus ist. Aber die ASPM-Politik gilt auf Ebene des Links, nicht auf Ebene des Geräts. Die ASPM-Politik des Hosts gilt weiterhin für den physischen Link, weil der Host weiterhin die PCIe-Topologie besitzt.

VFIO fängt ASPM-Wechsel nicht ab und überschreibt sie nicht. Es reicht den BAR-Bereich und die Interrupts des Geräts durch, aber die Energieverwaltung des Links bleibt in der Hand des Hosts. Der Gast hat keinen Weg, dem Host zu sagen „halte diesen Link in L0“.

Der Gast besitzt das Gerät, der Host besitzt weiterhin den Link — und es gibt keinen Kanal dazwischenGast-VMNVMe-Treiberbesitzt das Gerät, schickt das IO abHost-KernelPCIe-SubsystemASPM-Politikvfio-pciD-Zustands-Politikkein Weg zu sagen„Link in L0 halten“physischer PCIe-Link — in L1, schlafenddas entscheidet der Host, nicht der GastHost sieht keinenTreiber, also lässter den Link schlafenGast schickt IO abund erwartet L0dieses IO wartet, bis der Link aufwacht — 2–32 µs, aus L1.2 bis zu 100 µsVFIO reicht BAR-Bereich und Interrupts durch. Die Energieverwaltung des Links gehört nicht dazu.Die meisten IOs treffen den schlafenden Link gar nicht, deshalb bewegt sich nur der Ausläufer.
Die Trennung, die es verursacht: der Gast besitzt das Gerät und schickt das IO ab, der Host besitzt den Link und entscheidet, wann er schläft, und nichts verbindet die beiden.

Manche neuere Hardware und manche Kernel-Versionen kommen damit besser zurecht als andere. Damit ist der sicherste Weg, ASPM ganz aus dem Bild zu nehmen.

Wie man es abschaltet

Füge pcie_aspm=off zur Kernel-Kommandozeile des Hosts hinzu:

# Edit /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet pcie_aspm=off"

# Update GRUB and reboot
update-grub
reboot

Das verhindert, dass der Host irgendeinen PCIe-Link in einen Zustand mit geringer Leistung versetzt. Es gilt global. Jedes PCIe-Gerät auf dem Host, nicht nur das durchgereichte.

Nach dem Neustart prüfen:

# Should show "ASPM Disabled" for all devices
lspci -vv | grep -i "ASPM"

Was es an Strom kostet

ASPM abzuschalten erhöht den Stromverbrauch im Ruhezustand. Jeder PCIe-Link, der sonst in L1 wäre, bleibt in L0 und zieht ein paar hundert Milliwatt mehr. Über ein System mit zehn oder fünfzehn PCIe-Geräten kommen so 2–5 Watt im Ruhezustand zusammen.

Für einen Server im Rechenzentrum sind 2–5 Watt ein Rundungsfehler auf der Stromrechnung. Für ein Homelab sind sie ein Bruchteil dessen, was CPU und Speicher ziehen. Für einen Laptop zählen sie. Aber VFIO-Passthrough würdest du auf einem Laptopakku auch nicht machen.

Der Handel ist klar. Ein paar Watt im Ruhezustand gegen unvorhersehbare Latenzspitzen auf deinen durchgereichten Geräten. Auf jedem System mit Passthrough sollte ASPM aus sein.

Probleme mit Energiezuständen auf Geräteebene

ASPM steuert den Energiezustand des PCIe-Links. Geräte haben auch ihre eigene Energieverwaltung — die PCIe-D-Zustände (D0 bis D3).

Ist ein Gerät in D3 (vollständig heruntergefahren), schläft nicht nur der Link. Das Gerät selbst hat angehalten. Unter VFIO-Passthrough kann der vfio-pci-Treiber des Hosts das Gerät in D3 versetzen, wenn die VM nicht läuft oder wenn die Energiepolitik des Hosts das Gerät für unbeschäftigt hält.

Manche NVMe-Controller kommen mit dem Wechsel von D3 zurück nach D0 nicht sauber zurecht. Sie kommen nicht sauber wieder, der Gast verliert das Gerät, und der einzige Ausweg ist ein Neustart der VM oder manchmal ein Neustart des Hosts.

Die Samsung 990 EVO Plus ist ein bekannter Übeltäter. Die Lösung ist die Modul-Option disable_idle_d3 für vfio-pci:

# /etc/modprobe.d/vfio.conf
options vfio-pci disable_idle_d3=1

Das verhindert, dass vfio-pci ein gebundenes Gerät im Ruhezustand in D3 versetzt. Wie pcie_aspm=off ist es eine globale Einstellung. Jedes an vfio-pci gebundene Gerät bleibt in D0. Beim Passthrough ist das meist genau, was du willst, denn dort sollte der Gast das Einzige sein, was den Energiezustand des Geräts steuert.

Die Option disable_idle_d3 hat mit ASPM nichts zu tun. ASPM steuert den Link. D3 steuert das Gerät. Beide können unabhängig voneinander Probleme machen. Für eine saubere Passthrough-Konfiguration schalte beide ab.

ASPM pro Gerät steuern

Willst du ASPM nicht global abschalten — vielleicht hast du andere PCIe-Geräte auf dem Host, die von der Stromsparfunktion profitieren —, kannst du ASPM pro Link über sysfs steuern:

# Find the link's ASPM policy
cat /sys/bus/pci/devices/0000:XX:00.0/link/l1_aspm

# Disable ASPM for a specific link
echo 0 > /sys/bus/pci/devices/0000:XX:00.0/link/l1_aspm

Das ist zielgenauer, aber über Neustarts und Kernel-Aktualisierungen hinweg weniger verlässlich. Für die meisten Passthrough-Aufbauten ist das globale Kernel-Flag pcie_aspm=off einfacher und vorhersehbarer.

Wenn ASPM nicht das Problem ist

Nicht jedes Latenzzittern ist ASPM.

Sind deine clat-Perzentile durchgehend hoch (nicht nur am Ausläufer), liegt das Problem eher an Overhead der IOMMU-Übersetzung, an NUMA-Fehlausrichtung oder an einer MPS-Fehlanpassung. ASPM erzeugt speziell ein zweigipfliges Muster — die meisten IOs sind schnell, ein paar sind langsam —, weil es nur die IOs trifft, die zufällig eintreffen, während der Link in einem Zustand mit geringer Leistung liegt.

Prüf auf ASPM zuerst, wenn du siehst:

  • p99-Latenz 5-mal oder mehr über dem Durchschnitt
  • ungleichmäßige fio-Ergebnisse zwischen Durchläufen
  • Latenz, die unter Dauerlast besser wird und bei stoßweiser Arbeit schlechter

Ist die Latenz unabhängig vom Lastmuster durchgehend schlecht, schau woanders. ASPM ist es wert, früh ausgeschlossen zu werden, weil es billig zu testen ist. Es ist aber nicht die Antwort auf jeden langsamen Link, und ihm hinterherzujagen, wenn die Zahlen nicht zum Muster passen, ist ein Nachmittag, den du nicht zurückbekommst.

Quellen