Come forzare il kernel Linux a "congelare" (o quasi congelare) per alcune centinaia di millisecondi


17

Stiamo eseguendo un processo in tempo reale su un kernel non in tempo reale (CentOS 6), e questo probabilmente non cambierà.

Abbiamo un'applicazione di streaming video che richiede continuamente circa 500 MB / s di traffico PCIe da un FPGA personalizzato per 1,5 ore alla volta. L'applicazione funziona abbastanza bene, il più delle volte. Tuttavia, abbiamo riscontrato situazioni in cui sembra che il kernel smetta di rispondere alle richieste di memoria PCIe o di memoria per un massimo di 500 millisecondi alla volta. Ciò sembra accadere durante l'IO di file in sequenza da un altro thread. Ho trovato impossibile provare a replicare questo problema semplicemente facendo un sacco di file IO fittizi dallo spazio utente mentre l'applicazione principale è in esecuzione.

C'è un modo per forzare (simulare) un "blocco" globale del kernel Linux (in particolare, arrestando gli accessi alla memoria PCIe o DDR3 o qualcosa del genere) in modo da poter riprodurre questo problema?

Al momento abbiamo implementato fino a 10 millisecondi di buffer nella memoria FPGA interna, ma ciò non è sufficiente. È possibile eseguire il buffer su FPGA DDR3 e quindi eseguire il dump sull'host, ma è necessario un metodo per testare questa nuova funzionalità in caso di coercizione.

Non vogliamo che il kernel si blocchi o blocchi permanentemente. Vorremmo la possibilità di impostare l'intervallo di tempo.

Sto cercando qualcosa sulla falsariga di scrivere /proc/sys/vmtemporaneamente valori magici che faccia strisciare virtualmente il sistema, per poi tornare indietro dopo alcune centinaia di millisecondi, ma guardare il numero di possibili modi per romperlo non è per un principiante come me ( https://www.kernel.org/doc/Documentation/sysctl/vm.txt ). Forse un po 'di numactlmagia?


La mia impressione è che ciò richiede la scrittura di un modulo del kernel. Dovrai bloccare tutti i thread su tutte le CPU in qualche modo e organizzare il riavvio in caso di interruzione del timer.
Gilles 'SO- smetti di essere malvagio'

Non voglio congelare i thread, voglio congelare il kernel! Voglio dire, voglio impedire l'accesso all'hardware (memoria e / o PCIe e / o disco) per un breve periodo. Se non funziona, non mi dispiace rendere le cose molto non ottimizzate, disabilitare la cache L1, ecc. Non so proprio come fare.
Mark Lakata,

1
Ah, quindi non vuoi congelare il kernel, vuoi solo congelare la parte del kernel che risponde a qualche hardware? Anche questo richiederebbe un'immersione abbastanza profonda nel kernel.
Gilles 'SO- smetti di essere malvagio' il

Non mi dispiace congelare completamente il kernel, purché l'hardware sia bloccato come parte di esso.
Mark Lakata,

1
Si scopre che il problema è legato al thrashing TLB poiché la CPU host scarica alcuni buffer IO (stiamo usando HDF5 per scrivere file), e questo thrashing TLB sta causando il thrash del coprocessore, poiché si tratta di un sistema NUMA. Immagino che tutto ciò di cui abbiamo bisogno ora sia un modo affidabile di causare a livello programmatico il thrashing TLB per un periodo di tempo controllato.
Mark Lakata,

Risposte:


9

Un'opzione per eseguire un test rapido potrebbe essere quella di utilizzare un kernel abilitato a KGDB e arrestare il kernel manualmente e testare, vedere questo collegamento .

In un'altra nota, le cose che ricordo che potrebbero causare le tue pause:

  • cpufreq, cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_transition_latencyil valore è in ns (4000 nel mio processore AMD FX (tm) -8120 a otto core) non dovrebbe essere un problema, ma controlla
  • Limitazione termica della CPU stessa o del modulo regolatore di tensione.
  • NAPI e / o traffico di rete pesante
  • PCIe ASPM ( cat /sys/module/pcie_aspm/parameters/policy)
  • Contesa nei buffer del dispositivo di destinazione (disco rigido, nic ...)
  • Bug nel firmware di alcuni dispositivi nel bus PCIe (anche se non lo si utilizza), è possibile provare a spegnerli con /sys/bus/pci/devices/$DEVICE/power/control

Potrei usare kdbinvece di kgdbfare lo stesso? Nemmeno io l'ho mai usato. È come la sequenza di comandi "Stop-A" sulle workstation Sun di un tempo? Se faccio solo un rapido SysRq-g, quindi digito "go", avrò un'alta probabilità di non rompere il sistema? (ref: kernel.org/pub/linux/kernel/people/jwessel/kdb/... )
Mark Lakata

1
Probabilmente sarai in grado di usare kdb. Ricorda che dovrebbe funzionare con le tastiere USB, ma cerca di averne una PS / 2 a portata di mano per ogni evenienza. E questo è un debugger di livello molto basso (kernel land), quindi come sempre, conserva i backup e se si rompe riesci a conservare entrambi i pezzi :).
Jorge Nerín,

Prima di ricorrere alla modifica con il kernel, proverei innanzitutto a scaricare i moduli del kernel inutilizzati per i dispositivi PCIe che potrebbero utilizzare il bus (driver grafici in particolare) e rimuovere fisicamente i dispositivi dal sistema o spegnerli. PCIe 1.0 x1 ha una larghezza di banda di 250 MB / se PCIe 2.0 x1 arriva a 500 MB / s, sia il dispositivo di origine che quello di destinazione sono liberi di accettare tale frequenza sostenuta senza interruzioni o hanno più corsie per consentire più spazio?
Jorge Nerín

Un'altra possibile fonte del ritardo potrebbe essere un gestore di gestione dell'alimentazione ACPI di un dispositivo o forse un gestore di CPU SMM in attesa di un evento esterno.
Franki,

2

Possiamo avere maggiori dettagli su come l'applicazione comunica con l'FPGA? È l'applicazione che legge il buffer dall'FPGA o l'FPGA che invia interrupt al kernel (come le schede di rete)?

Mi aspetto che apra un blocco / carattere in / dev e poi comunichi con esso. Ciò significa che utilizza un driver per effettuare la comunicazione tra l'applicazione e il file / dev / XXX.

Mi piacerebbe avere l'output di cat /proc/interrupts:; lsmod;ls -al /dev/yourmod

Ecco le idee:

  • Se è guidato dall'interruzione, è possibile impostare il PIC della CPU per disabilitare l'IRQ corrispondente, quindi riattivarlo. Questo farà sì che ogni richiesta della carta venga ignorata (senza che la carta ne sia consapevole).
  • se è come un buffer letto, puoi:
    • Metti la tua applicazione in stato di sospensione, così i dati dall'FPGA non verranno letti e il buffer si riempirà, quindi riattiva l'applicazione e continua la lettura.
    • Utilizzare "crash" o "kgdb" per modificare il valore "read" in "noop" per alcuni secondi, quindi ripristinarlo alla funzione predefinita.

Fornisci tutte le informazioni che potresti trovare utili.


FPGA scrive DMA nella memoria host e durante questi periodi di interruzione, FPGA non è in grado di scrivere nella memoria host, quindi il backup FIFO interno è in grado di eseguire il backup. Esiste un'interfaccia basata sui messaggi per il processo host (avviene tramite PCIe), ma sono certo che non è coinvolto. Ai fini della validazione, ho sostanzialmente bisogno di un modo per proibire all'hardware FPGA di scrivere nella memoria host per alcune centinaia di millisecondi. Non voglio risolvere il problema di memoria, ma voglio assicurarmi che la nostra implementazione sull'FPGA sia in grado di gestire un'interruzione della memoria (fino a 1000 ms).
Mark Lakata,

Ok, se sta usando DMA, puoi dare un'occhiata a: kernel.org/doc/Documentation/DMA-ISA-LPC.txt in particolare su claim_dma_lock () e dma_disable (). Tuttavia, dovrai conoscere gli indirizzi utilizzati dal tuo FPGA.
Adrien M.,

1

Non sono sicuro se aiuta. Ma se riesci a scrivere un modulo del kernel che chiama la suspendfunzione del modulo del kernel di un altro dispositivo, è possibile.

Ogni dispositivo PCI può essere sospeso in base al file di intestazione http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/pci.h#L479

Ad esempio, ecco la funzione di sospensione di Intel e1000 NIC http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/e1000e/netdev.c#L4643

Da quello che posso ricordare, questa funzione è stata utilizzata principalmente quando il sistema va in letargo, il driver del dispositivo deve salvare lo stato corrente e spegnersi.


grazie, ma non credo che funzionerà. Non voglio davvero sospendere un dispositivo, che è il kernel che dice al dispositivo di prepararsi per l'ibernazione; Voglio che il kernel ignori il dispositivo specifico (in questo caso la scheda figlia FPGA) senza che lo sappia (oltre a latenze lunghe o timeout) - o voglio interrompere tutti i trasferimenti di memoria SDRAM.
Mark Lakata,

0

Penso che tu stia pensando nella direzione sbagliata. Il tuo obiettivo è chiaro

Il modo non è quello di fermare il resto dei processi ma di dare ai tuoi processi principali una priorità di sceduling in tempo reale. Usa nice per i tuoi importanti processi di spazio utente per quello.

Il problema più difficile è la gestione degli interrupt PCIe, che risiede nello spazio del kernel.

Poiché è coinvolto l'hardware, dovresti iniziare a dare un'occhiata più da vicino alla corsia PCIe interessata sulla tua scheda madre e al modo in cui è eventualmente collegato a un socket CPU specifico.

normalmente irqbalance fa un buon lavoro qui, ma potresti configurarne il comportamento in base alle tue esigenze.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.