Comment forcer le noyau Linux à «geler» (ou presque geler) pendant quelques centaines de millisecondes


17

Nous exécutons un processus en temps réel sur un noyau non temps réel (CentOS 6), et cela ne va probablement pas changer.

Nous avons une application de streaming vidéo qui nécessite environ 500 Mo / s de trafic PCIe à partir d'un FPGA personnalisé en continu pendant 1,5 heure à la fois. L'application fonctionne plutôt bien - la plupart du temps. Cependant, nous avons eu des situations où il semble que le noyau cesse de répondre aux demandes de maintenance PCIe ou de mémoire pendant jusqu'à 500 millisecondes à la fois. Cela semble se produire pendant les E / S de fichiers en rafale à partir d'un autre thread. J'ai trouvé impossible d'essayer de reproduire ce problème en faisant simplement beaucoup d'E / S de fichiers factices à partir de l'espace utilisateur pendant que l'application principale est en cours d'exécution.

Existe-t-il un moyen de forcer (simuler) un "gel" global du noyau Linux (en particulier, arrêter PCIe ou tous les accès à la mémoire DDR3 ou quelque chose comme ça) afin que nous puissions reproduire ce problème?

Nous avons mis en mémoire tampon jusqu'à 10 millisecondes en ce moment dans la mémoire FPGA interne, mais ce n'est pas suffisant. Nous pouvons mettre en mémoire tampon sur FPGA DDR3 puis vider sur l'hôte, mais nous avons besoin d'une méthode pour tester cette nouvelle fonctionnalité sous la contrainte.

Nous ne voulons pas que le noyau se fige ou se bloque définitivement. Nous aimerions pouvoir définir l'intervalle de temps.

Je cherche quelque chose dans le sens d'écrire /proc/sys/vmtemporairement des valeurs magiques qui rend le système pratiquement ramper, puis revenir en arrière après quelques centaines de millisecondes, mais regarder le nombre de façons possibles de le casser n'est pas pour un débutant comme moi ( https://www.kernel.org/doc/Documentation/sysctl/vm.txt ). Peut-être un peu de numactlmagie?


Mon intuition est que cela nécessite d'écrire un module du noyau. Vous devrez geler tous les threads sur tous les processeurs d'une manière ou d'une autre et organiser le redémarrage en cas d'interruption du minuteur.
Gilles 'SO- arrête d'être méchant'

Je ne veux pas geler les threads, je veux geler le noyau! Je veux dire, je veux empêcher l'accès au matériel (mémoire et / ou PCIe et / ou disque) pendant une courte période. Si cela ne fonctionne pas, cela ne me dérange pas de rendre les choses très peu optimisées, de désactiver le cache L1, etc. Je ne sais tout simplement pas comment faire cela.
Mark Lakata

1
Ah, donc vous ne voulez pas geler le noyau, vous voulez seulement geler la partie du noyau qui répond à du matériel? Cela aussi nécessiterait une plongée assez profonde dans le noyau.
Gilles 'SO- arrête d'être méchant'

Cela ne me dérange pas de geler complètement le noyau, tant que le matériel est figé dans le cadre de celui-ci.
Mark Lakata

1
Il s'avère que le problème est lié au thrashing TLB car le processeur hôte vide certains tampons IO (nous utilisons HDF5 pour écrire des fichiers), et ce thrash TLB provoque également le thrash du coprocesseur, car il s'agit d'un système NUMA. Je suppose que tout ce dont nous avons besoin maintenant est un moyen fiable de provoquer par programmation le thrash TLB pendant une durée contrôlée.
Mark Lakata

Réponses:


9

Une option pour faire un test rapide pourrait être d'utiliser un noyau compatible KGDB et d'arrêter le noyau manuellement et de tester, voir ce lien .

Sur une autre note, les choses dont je me souviens qui pourraient provoquer vos pauses:

  • cpufreq, cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_transition_latencyla valeur est en ns (4000 dans mon processeur AMD FX (tm) -8120 à huit cœurs) ne devrait pas être un problème, mais vérifiez
  • Étranglement thermique soit du processeur lui-même, soit du module régulateur de tension.
  • NAPI et / ou trafic réseau important
  • PCIe ASPM ( cat /sys/module/pcie_aspm/parameters/policy)
  • Contention dans les tampons de votre appareil de destination (disque dur, nic ...)
  • Bug dans le firmware de certains périphériques du bus PCIe (même si vous ne l'utilisez pas), vous pouvez essayer de les éteindre avec /sys/bus/pci/devices/$DEVICE/power/control

Puis-je utiliser kdbau lieu de kgdbfaire de même? Je n'en ai jamais utilisé non plus. Est-ce comme la séquence de commandes "Stop-A" sur les postes de travail Sun d'antan? Si je fais juste un SysRq-g rapide, puis tape "go", aurai-je une forte probabilité de ne pas casser le système? (ref: kernel.org/pub/linux/kernel/people/jwessel/kdb/… )
Mark Lakata

1
Vous pourrez probablement utiliser kdb. Sachez que cela devrait fonctionner avec les claviers connectés en USB, mais essayez d'avoir un PS / 2 à portée de main au cas où. Et c'est un débogueur de très bas niveau (kernel land), donc comme toujours, gardez les sauvegardes et si ça casse, vous pouvez garder les deux morceaux :).
Jorge Nerín

Avant de recourir à des ajustements avec le noyau, j'essaierais d'abord de décharger les modules du noyau inutilisés pour les périphériques PCIe qui pourraient utiliser le bus (les pilotes graphiques notamment), et de retirer physiquement les périphériques du système ou de les éteindre. PCIe 1.0 x1 a une bande passante de 250 Mo / s et PCIe 2.0 x1 va jusqu'à 500 Mo / s, les périphériques d'origine et de destination sont-ils libres d'accepter un tel taux soutenu sans interruption ou ont-ils plus de voies pour permettre plus d'espace libre?
Jorge Nerín

Une autre source possible de retard pourrait être un gestionnaire de gestion de l'alimentation ACPI d'un périphérique ou peut-être même un gestionnaire de processeur SMM en attente d'un événement externe.
Franki

2

Pouvons-nous avoir plus de détails sur la façon dont votre application communique avec le FPGA? Est-ce l'application qui lit le tampon du FPGA, ou le FPGA qui envoie une interruption au noyau (comme les cartes réseau)?

Je m'attends à ce qu'il ouvre un bloc / char dans / dev puis communique avec lui. Cela signifie qu'il utilise un pilote pour établir la communication entre l'application et le fichier / dev / XXX.

J'aimerais avoir la sortie de cat /proc/interrupts:; lsmod;ls -al /dev/yourmod

Voici les idées:

  • S'il est déclenché par interruption, vous pouvez définir le PIC du CPU pour désactiver l'IRQ correspondant, puis le réactiver. Cela entraînera l'ignorance de chaque demande de la carte (sans que la carte en soit consciente).
  • si c'est comme une lecture tampon, vous pouvez:
    • Mettez votre application en veille afin que les données du FPGA ne soient pas lues et que votre tampon se remplisse, puis réveillez votre application et poursuivez la lecture.
    • Utilisez "crash" ou "kgdb" pour changer la valeur "read" en "noop" pendant quelques secondes, puis redéfinissez-la sur la fonction par défaut.

Veuillez fournir toutes les informations que vous jugerez utiles.


Le FPGA effectue des écritures DMA sur la mémoire hôte, et pendant ces périodes d'interruption, le FPGA n'est pas en mesure d'écrire sur la mémoire hôte, donc sa sauvegarde FIFO interne. Il existe une interface basée sur des messages pour le processus hôte (se produit sur PCIe), mais je suis certain que cela n'est pas impliqué. À des fins de validation, j'ai essentiellement besoin d'un moyen d'interdire au matériel FPGA d'écrire sur la mémoire hôte pendant quelques centaines de millisecondes. Je ne veux pas résoudre le problème de mémoire, mais je veux m'assurer que notre implémentation sur le FPGA est capable de faire face à une panne de mémoire (jusqu'à 1000 ms).
Mark Lakata

Ok, s'il utilise DMA, vous pouvez consulter: kernel.org/doc/Documentation/DMA-ISA-LPC.txt en particulier sur claim_dma_lock () et dma_disable (). Cependant, vous devrez connaître les adresses utilisées par votre FPGA.
Adrien M.

1

Je ne sais pas si cela aide. Mais si vous pouvez écrire un module noyau qui appelle la suspendfonction du module noyau d'un autre périphérique, cela peut le faire.

Chaque périphérique PCI peut être suspendu conformément au fichier d'en-tête http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/pci.h#L479

Par exemple, voici la fonction de suspension de la carte réseau Intel e1000 http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/e1000e/netdev.c#L4643

D'après ce dont je me souviens, cette fonction était principalement utilisée lorsque le système passe en veille prolongée, le pilote de périphérique doit enregistrer l'état de fonctionnement actuel et s'éteindre.


merci, mais je ne pense pas que cela fonctionnera. Je ne veux pas vraiment suspendre un périphérique, c'est le noyau qui dit au périphérique de se préparer pour l'hibernation; Je veux que le noyau ignore le périphérique spécifique (dans ce cas, la carte fille FPGA) sans qu'il le sache (autre que les longues latences ou les délais d'attente) - ou je veux arrêter tous les transferts de mémoire SDRAM.
Mark Lakata

0

Je pense que vous pensez dans le mauvais sens. Votre objectif est clair.

Le moyen n'est pas d'arrêter le reste des processus mais de donner à vos principaux processus une priorité de planification en temps réel. Utilisez nice pour vos processus d'espace utilisateur importants pour cela.

Le problème le plus difficile est la gestion des interruptions PCIe, qui réside dans l'espace noyau.

Étant donné que le matériel est impliqué, vous devriez commencer à regarder de plus près la voie PCIe impliquée sur votre carte mère et comment elle est éventuellement connectée à un socket CPU spécifique.

irqbalance fait normalement du bon travail ici, mais vous pouvez configurer son comportement en fonction de vos besoins.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.