Jak zmusić jądro Linuksa do „zamrożenia” (lub prawie zamrożenia) na kilkaset milisekund

17

Prowadzimy proces w czasie rzeczywistym na jądrze nie działającym w czasie rzeczywistym (CentOS 6) i prawdopodobnie nie ulegnie to zmianie.

Mamy aplikację do przesyłania strumieniowego wideo, która wymaga około 500 MB / s ruchu PCIe z niestandardowego układu FPGA przez 1,5 godziny bez przerwy. Aplikacja działa całkiem dobrze - przez większość czasu. Jednak zdarzały się sytuacje, w których wydaje się, że jądro po prostu przestaje odpowiadać na obsługę żądań PCIe lub pamięci przez maksymalnie 500 milisekund na raz. Wydaje się, że tak się dzieje podczas IO pliku bursty z innego wątku. Nie udało mi się spróbować replikować tego problemu, po prostu wykonując wiele fałszywych operacji we / wy pliku z przestrzeni użytkownika podczas działania głównej aplikacji.

Czy istnieje sposób na wymuszenie (symulację) globalnego „zamrożenia” jądra systemu Linux (w szczególności zatrzymanie dostępu do pamięci PCIe lub całego DDR3 itp.), Abyśmy mogli odtworzyć ten problem?

Buforujemy do 10 milisekund zaimplementowanych teraz w wewnętrznej pamięci FPGA, ale to nie wystarczy. Możemy buforować do FPGA DDR3, a następnie zrzucić do hosta, ale potrzebujemy metody przetestowania tej nowej funkcji pod przymusem.

Nie chcemy, aby jądro zawiesiło się lub zablokowało na stałe. Chcielibyśmy możliwość ustawienia odstępu czasu.

Szukam czegoś w stylu pisania magicznych wartości, które /proc/sys/vmtymczasowo powodują, że system wirtualnie się czołga, a następnie wraca do poprzedniego poziomu po kilkuset milisekundach, ale patrząc na liczbę możliwych sposobów jego złamania, nie jest to dla początkujących jak ja ( https://www.kernel.org/doc/Documentation/sysctl/vm.txt ). Może trochę numactlmagii?

Mark Lakata
źródło
Mam przeczucie, że to wymaga napisania modułu jądra. Będziesz musiał jakoś zamrozić wszystkie wątki na wszystkich procesorach i zorganizować restart po przerwaniu timera.
Gilles „SO- przestań być zły”
Nie chcę zamrażać wątków, chcę zamrażać jądro! Chcę przez krótki czas uniemożliwić dostęp do sprzętu (pamięci i / lub PCIe i / lub dysku). Jeśli to nie zadziała, nie mam nic przeciwko robieniu rzeczy niezoptymalizowanych, wyłączaniu pamięci podręcznej L1 itp. Po prostu nie wiem, jak to zrobić.
Mark Lakata,
1
Ach, więc nie chcesz zamrozić jądra, chcesz tylko zamrozić część jądra, która reaguje na jakiś sprzęt? To także wymagałoby nurkowania dość głęboko w jądrze.
Gilles „SO- przestań być zły”
Nie mam nic przeciwko całkowitemu zamrożeniu jądra, o ile sprzęt jest zamrożony w jego ramach.
Mark Lakata,
1
Okazuje się, że problem związany jest z thrashowaniem TLB, ponieważ CPU hosta opróżnia niektóre bufory IO (używamy HDF5 do zapisywania plików), a to thrashing TLB powoduje, że koprocesor także thrash, ponieważ jest to system NUMA. Chyba wszystko, czego teraz potrzebujemy, to niezawodny sposób programowego powodowania thrashingu TLB przez kontrolowany okres czasu.
Mark Lakata,

Odpowiedzi:

9

Jedną z opcji szybkiego testu może być użycie jądra z włączoną funkcją KGDB i ręczne zatrzymanie jądra i przetestowanie, zobacz ten link .

Z drugiej strony, rzeczy, które pamiętam, które mogą powodować twoje przerwy:

  • cpufreq, cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_transition_latencywartość jest w ns (4000 w moim ośmiordzeniowym procesorze AMD FX (tm) -8120) nie powinno stanowić problemu, ale sprawdź
  • Ograniczanie temperatury zarówno samego procesora, jak i modułu regulatora napięcia.
  • NAPI i / lub duży ruch sieciowy
  • PCIe ASPM ( cat /sys/module/pcie_aspm/parameters/policy)
  • Zawartość w buforach urządzenia docelowego (dysk twardy, nic ...)
  • Błąd w oprogramowaniu wewnętrznym niektórych urządzeń na magistrali PCIe (nawet jeśli go nie używasz), możesz spróbować je wyłączyć za pomocą /sys/bus/pci/devices/$DEVICE/power/control
Jorge Nerín
źródło
Czy mogę użyć kdbzamiast kgdbtego samego? Nigdy też nie użyłem. Czy to jest jak sekwencja poleceń „Stop-A” na stacjach roboczych firmy Sun w przeszłości? Jeśli po prostu zrobię szybki SysRq-g, a następnie wpisz „go”, czy będę mieć duże prawdopodobieństwo, że nie zepsuje systemu? (zob .: kernel.org/pub/linux/kernel/people/jwessel/kdb/… )
Mark Lakata
1
Prawdopodobnie będziesz w stanie korzystać z kdb. Pamiętaj, że powinien on współpracować z klawiaturami podłączonymi przez USB, ale na wszelki wypadek postaraj się mieć PS / 2. Jest to debugger bardzo niskiego poziomu (jądro), więc jak zawsze przechowuj kopie zapasowe, a jeśli się zepsuje, zachowaj oba elementy :).
Jorge Nerín
Zanim zacznę ulepszać jądro, najpierw spróbuję zwolnić nieużywane moduły jądra dla urządzeń PCIe, które mogą korzystać z magistrali (w szczególności sterowników graficznych) i albo fizycznie usuwając urządzenia z systemu, albo je wyłączając. PCIe 1.0 x1 ma przepustowość 250 MB / s, a PCIe 2.0 x1 zwiększa się do 500 MB / s, czy zarówno urządzenie początkowe, jak i docelowe może swobodnie akceptować taką stałą szybkość bez zakłóceń, czy też mają więcej pasów, aby zapewnić więcej miejsca na zapas?
Jorge Nerín
Innym możliwym źródłem opóźnienia może być moduł obsługi zasilania ACPI jakiegoś urządzenia lub nawet moduł obsługi procesora SMM czekający na zdarzenie zewnętrzne.
Franki
2

Czy możemy uzyskać więcej informacji na temat sposobu, w jaki Twoja aplikacja komunikuje się z FPGA? Czy to aplikacja odczytuje bufor z FPGA, czy FPGA, która wysyła przerwanie do jądra (jak karty sieciowe)?

Oczekuję, że otworzy blok / char w / dev, a następnie się z nim komunikuje. Oznacza to, że używa sterownika do komunikacji między aplikacją a plikiem / dev / XXX.

Chciałbym mieć wynik cat /proc/interrupts:; lsmod;ls -al /dev/yourmod

Oto pomysły:

  • Jeśli jest sterowane przerwaniem, możesz ustawić procesor PIC tak, aby wyłączał odpowiednie przerwanie IRQ, a następnie włączyć go ponownie. Spowoduje to, że każde żądanie karty zostanie zignorowane (bez wiedzy karty).
  • jeśli przypomina odczyt bufora, możesz:
    • Przełącz aplikację w stan uśpienia, aby dane z FPGA nie zostały odczytane, a bufor się zapełni, a następnie obudź aplikację i kontynuuj czytanie.
    • Użyj „crash” lub „kgdb”, aby na kilka sekund zmienić wartość „read” na „noop”, a następnie przywróć domyślną funkcję.

Podaj wszystkie informacje, które mogą okazać się przydatne.

Adrien M.
źródło
FPGA dokonuje zapisów DMA w pamięci hosta, a podczas tych okresów przestoju FPGA nie jest w stanie zapisywać w pamięci hosta, więc wewnętrzne tworzenie kopii zapasowej FIFO. Istnieje interfejs oparty na komunikatach do procesu hosta (dzieje się to za pośrednictwem PCIe), ale jestem pewien, że nie jest to zaangażowane. Do celów sprawdzania poprawności zasadniczo potrzebuję sposobu, aby sprzęt FPGA nie zapisywał w pamięci hosta przez kilkaset milisekund. Nie chcę rozwiązać problemu z pamięcią, ale chcę się upewnić, że nasza implementacja na FPGA jest w stanie poradzić sobie z brakiem pamięci (do 1000 ms).
Mark Lakata,
Ok, jeśli używa DMA, możesz zajrzeć na: kernel.org/doc/Documentation/DMA-ISA-LPC.txt szczególnie na Claude_dma_lock () i dma_disable (). Musisz jednak znać adresy używane przez układ FPGA.
Adrien M.,
1

Nie jestem pewien, czy to pomaga. Ale jeśli możesz napisać moduł jądra, który wywołuje suspendfunkcję modułu jądra innego urządzenia, może to zrobić.

Każde urządzenie PCI można zawiesić zgodnie z plikiem nagłówka http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/pci.h#L479

Na przykład, oto funkcja zawieszenia karty Intel e1000 NIC http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/e1000e/netdev.c#L4643

Z tego co pamiętam, ta funkcja była używana głównie, gdy system przechodzi w stan hibernacji, sterownik urządzenia musi zapisać bieżący stan działania i sam się wyłączyć.

czatować
źródło
dzięki, ale nie sądzę, żeby to zadziałało. Tak naprawdę nie chcę zawiesić urządzenia, które jest jądrem, które każe urządzeniu przygotować się do hibernacji; Chcę, aby jądro zignorowało określone urządzenie (w tym przypadku kartę-córkę FPGA) bez jego wiedzy (inne niż długie opóźnienia lub przekroczenia limitu czasu) - lub chcę zatrzymać wszystkie transfery pamięci SDRAM.
Mark Lakata
0

Myślę, że myślisz niewłaściwie. Twój cel jest jasny.

Sposób nie polega na zatrzymaniu reszty procesów, ale nadaniu głównym procesom priorytetu scedulowania w czasie rzeczywistym. Użyj miły dla swoich użytkowników ważnych procesów przestrzenią za to.

Trudniejszym problemem jest obsługa przerwań PCIe, która znajduje się w przestrzeni jądra.

Ponieważ w grę wchodzi sprzęt, powinieneś bliżej przyjrzeć się zaangażowanemu paskowi PCIe na płycie głównej i sposobowi, w jaki jest on podłączony do określonego gniazda procesora.

irqbalance zazwyczaj wykonuje dobrą robotę, ale możesz skonfigurować jego zachowanie, aby odpowiadało twoim potrzebom.

Nils
źródło