So zwingen Sie den Linux-Kernel, einige hundert Millisekunden lang "einzufrieren" (oder fast einzufrieren)

17

Wir führen einen Echtzeitprozess auf einem Nicht-Echtzeit-Kernel (CentOS 6) aus, und dies wird sich wahrscheinlich nicht ändern.

Wir haben eine Streaming-Video-Anwendung, die 1,5 Stunden lang ununterbrochen ca. 500 MB / s PCIe-Datenverkehr von einem benutzerdefinierten FPGA benötigt. Die Anwendung funktioniert ziemlich gut - die meiste Zeit. Es gab jedoch Situationen, in denen der Kernel anscheinend nur bis zu 500 Millisekunden lang nicht mehr auf PCIe- oder Speicheranforderungen reagiert. Dies scheint während der Bursty-Datei-E / A von einem anderen Thread zu geschehen. Ich fand es unmöglich, zu versuchen, dieses Problem zu replizieren, indem ich nur viel Dummy-Datei-E / A aus dem Benutzerbereich ausführte, während die Hauptanwendung ausgeführt wurde.

Gibt es eine Möglichkeit, ein globales "Einfrieren" des Linux-Kernels zu erzwingen (simulieren) (insbesondere das Stoppen von PCIe oder aller DDR3-Speicherzugriffe oder dergleichen), damit wir dieses Problem reproduzieren können?

Wir haben bis zu 10 Millisekunden im internen FPGA-Speicher gepuffert, aber das ist nicht genug. Wir können auf FPGA DDR3 puffern und dann auf den Host sichern, aber wir benötigen eine Methode, um diese neue Funktion unter Zwang zu testen.

Wir möchten nicht, dass der Kernel dauerhaft einfriert oder blockiert. Wir möchten die Möglichkeit, das Zeitintervall einzustellen.

Ich bin auf der Suche nach etwas in der Art, wie man magische Werte /proc/sys/vmvorübergehend schreibt , um das System virtuell kriechen zu lassen, und dann nach ein paar hundert Millisekunden wieder zurück zu kehren. https://www.kernel.org/doc/Documentation/sysctl/vm.txt ). Vielleicht etwas numactlMagie?

Mark Lakata
quelle
Meine Vermutung ist, dass dies das Schreiben eines Kernelmoduls erfordert. Sie müssen alle Threads auf allen CPUs irgendwie einfrieren und bei einem Timer-Interrupt einen Neustart veranlassen.
Gilles 'SO- hör auf böse zu sein'
Ich möchte die Threads nicht einfrieren, ich möchte den Kernel einfrieren! Ich möchte den Zugriff auf Hardware (Speicher und / oder PCIe und / oder Festplatte) für kurze Zeit verhindern. Wenn das nicht funktioniert, macht es mir nichts aus, Dinge sehr unoptimiert zu machen, den L1-Cache zu deaktivieren usw. Ich weiß einfach nicht, wie das geht.
Mark Lakata
1
Ah, Sie wollen also den Kernel nicht einfrieren, sondern nur den Teil des Kernels einfrieren, der auf Hardware reagiert? Auch das würde ein ziemlich tiefes Eintauchen in den Kernel erfordern.
Gilles 'SO- hör auf böse zu sein'
Es macht mir nichts aus, den Kernel komplett einzufrieren, solange die Hardware als Teil davon eingefroren ist.
Mark Lakata
1
Es stellt sich heraus, dass das Problem mit dem TLB-Thrashing zusammenhängt, wenn die Host-CPU einige E / A-Puffer leert (wir verwenden HDF5 zum Schreiben von Dateien), und dieses TLB-Thrashing verursacht, dass der Coprozessor ebenfalls thrasht, da es sich um ein NUMA-System handelt. Ich denke, alles was wir jetzt brauchen, ist eine zuverlässige Methode, um TLB-Thrashing für eine kontrollierte Zeitdauer programmgesteuert auszulösen.
Mark Lakata

Antworten:

9

Eine Möglichkeit, einen Schnelltest durchzuführen, besteht darin, einen KGDB-fähigen Kernel zu verwenden und den Kernel manuell zu stoppen und zu testen ( siehe diesen Link) .

Außerdem erinnere ich mich an Dinge, die Ihre Pausen verursachen könnten:

  • cpufreq, cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_transition_latencyder Wert ist in ns (4000 in meinem AMD FX (tm) -8120 Eight-Core-Prozessor) sollte kein Problem sein, aber überprüfen
  • Thermische Drosselung entweder der CPU selbst oder des Spannungsreglermoduls.
  • NAPI und / oder starker Netzwerkverkehr
  • PCIe ASPM ( cat /sys/module/pcie_aspm/parameters/policy)
  • Konflikt in den Puffern Ihres Zielgeräts (Festplatte, Netzwerkkarte ...)
  • Fehler in der Firmware eines Geräts im PCIe-Bus (auch wenn Sie es nicht verwenden). Sie können versuchen, es mit auszuschalten /sys/bus/pci/devices/$DEVICE/power/control
Jorge Nerín
quelle
Könnte ich verwenden, kdbanstatt kgdbdasselbe zu tun? Ich habe auch noch nie benutzt. Entspricht dies der "Stop-A" -Befehlssequenz auf Sun-Workstations von gestern? Wenn ich nur ein kurzes SysRq-g mache, dann tippe "go". Habe ich eine hohe Wahrscheinlichkeit, das System nicht zu beschädigen? (Ref: kernel.org/pub/linux/kernel/people/jwessel/kdb/… )
Mark Lakata
1
Möglicherweise können Sie kdb verwenden. Seien Sie sich bewusst, dass es mit USB-Tastaturen funktionieren sollte, aber versuchen Sie, eine PS / 2-Tastatur zur Hand zu haben, nur für den Fall. Und das ist ein Debugger auf sehr niedriger Ebene (Kernel Land), also behalte wie immer Backups und wenn es kaputt geht, kannst du beide Teile behalten :).
Jorge Nerín
Bevor ich mich mit dem Kernel beschäftige, würde ich zuerst versuchen, unbenutzte Kernel-Module für PCIe-Geräte zu entladen, die den Bus nutzen könnten (vor allem Grafiktreiber), und entweder Geräte physisch vom System zu entfernen oder sie auszuschalten. PCIe 1.0 x1 hat eine Bandbreite von 250 MB / s und PCIe 2.0 x1 erreicht eine Geschwindigkeit von bis zu 500 MB / s. Können sowohl das Ursprungs- als auch das Zielgerät eine solche dauerhafte Rate ohne Unterbrechungen akzeptieren oder haben sie mehr Lanes, um mehr Headroom zu ermöglichen?
Jorge Nerín
Eine andere mögliche Ursache für die Verzögerung könnte ein ACPI-Energieverwaltungs-Handler eines Geräts oder sogar ein SMM-CPU-Handler sein, der auf ein externes Ereignis wartet.
Franki
2

Können wir weitere Informationen darüber erhalten, wie Ihre Anwendung mit dem FPGA kommuniziert? Ist es die Anwendung, die den Puffer vom FPGA liest, oder das FPGA, das einen Interrupt an den Kernel sendet (wie Netzwerkkarten)?

Ich erwarte, dass es einen Block / char in / dev öffnet und dann mit ihm kommuniziert. Dies bedeutet, dass für die Kommunikation zwischen der Anwendung und der Datei / dev / XXX ein Treiber verwendet wird.

Ich hätte gerne die Ausgabe von cat /proc/interrupts:; lsmod;ls -al /dev/yourmod

Hier sind die Ideen:

  • Wenn es Interrupt-gesteuert ist, können Sie den CPU-PIC so einstellen, dass der entsprechende IRQ deaktiviert und anschließend wieder aktiviert wird. Dadurch wird jede Anforderung der Karte ignoriert (ohne dass die Karte davon Kenntnis hat).
  • Wenn es wie ein Pufferlesevorgang ist, können Sie:
    • Versetzen Sie Ihre Anwendung in den Energiesparmodus, damit die Daten vom FPGA nicht gelesen werden und der Puffer sich füllt. Aktivieren Sie dann Ihre Anwendung und setzen Sie den Lesevorgang fort.
    • Verwenden Sie "crash" oder "kgdb", um den Wert "read" für einige Sekunden in "noop" zu ändern, und setzen Sie ihn dann auf die Standardfunktion zurück.

Bitte geben Sie alle Informationen an, die Sie als nützlich erachten.

Adrien M.
quelle
FPGA schreibt DMA in den Host-Speicher. Während dieser Ausfallzeiten kann der FPGA nicht in den Host-Speicher schreiben, sodass die interne FIFO-Sicherung ausgeführt wird. Es gibt eine nachrichtenbasierte Schnittstelle zum Host-Prozess (geschieht über PCIe), aber ich bin sicher, dass dies nicht betroffen ist. Für Validierungszwecke benötige ich grundsätzlich eine Möglichkeit, die FPGA-Hardware daran zu hindern, für einige hundert Millisekunden in den Hostspeicher zu schreiben. Ich möchte das Speicherproblem nicht lösen, aber ich möchte sicherstellen, dass unsere Implementierung auf dem FPGA in der Lage ist, einen Speicherausfall (bis zu 1000 ms) zu beheben.
Mark Lakata
Ok, wenn es DMA verwendet, können Sie einen Blick auf kernel.org/doc/Documentation/DMA-ISA-LPC.txt werfen, insbesondere auf claim_dma_lock () und dma_disable (). Sie müssen jedoch die von Ihrem FPGA verwendeten Adressen kennen.
Adrien M.
1

Ich bin mir nicht sicher, ob es hilft. Wenn Sie jedoch ein Kernelmodul schreiben können, das die suspendFunktion des Kernelmoduls eines anderen Geräts aufruft , ist dies möglicherweise ausreichend.

Jedes PCI-Gerät kann gemäß der Header-Datei http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/pci.h#L479 angehalten werden

Hier ist beispielsweise die Suspend-Funktion der Intel e1000-Netzwerkkarte: http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/e1000e/netdev.c#L4643

Soweit ich mich erinnern kann, wurde diese Funktion hauptsächlich verwendet, wenn das System in den Ruhezustand wechselt. Der Gerätetreiber muss den aktuellen Betriebsstatus speichern und sich selbst ausschalten.

Yegle
quelle
danke, aber ich glaube nicht, dass das funktionieren wird. Ich möchte ein Gerät nicht wirklich aussetzen, da dies der Kernel ist, der das Gerät auffordert, sich auf den Ruhezustand vorzubereiten. Ich möchte, dass der Kernel das spezifische Gerät (in diesem Fall die FPGA-Tochterplatine) ignoriert, ohne dass es davon Kenntnis hat (abgesehen von langen Latenzen oder Timeouts) - oder ich möchte alle SDRAM-Speicherübertragungen stoppen.
Mark Lakata
0

Ich denke, Sie denken in die falsche Richtung. Dein Ziel ist klar.

Der Weg ist nicht, den Rest der Prozesse anzuhalten, sondern Ihren Hauptprozessen eine zeitnahe Priorität einzuräumen. Verwenden Sie dazu nice für Ihre wichtigen User-Space-Prozesse.

Das schwierigere Problem ist die Handhabung von PCIe-Interrupts, die sich im Kernel-Space befindet.

Da es sich um Hardware handelt, sollten Sie sich die betroffene PCIe-Lane auf Ihrem Mainboard genauer ansehen und herausfinden, wie diese möglicherweise mit einem bestimmten CPU-Sockel verbunden ist.

Normalerweise macht irqbalance hier einen guten Job, aber Sie können das Verhalten so konfigurieren, dass es Ihren Bedürfnissen entspricht.

Nils
quelle