Como forçar o kernel do Linux a "congelar" (ou quase congelar) por algumas centenas de milissegundos

17

Estamos executando um processo em tempo real em um kernel não em tempo real (CentOS 6), e isso provavelmente não vai mudar.

Temos um aplicativo de streaming de vídeo que requer cerca de 500 MB / s de tráfego PCIe de um FPGA personalizado continuamente por 1,5 horas por vez. O aplicativo funciona muito bem - na maioria das vezes. No entanto, tivemos situações em que parece que o kernel simplesmente para de atender a solicitações de PCIe ou de memória por até 500 milissegundos por vez. Isso parece acontecer durante E / S de arquivo intermitente de outro encadeamento. Achei impossível tentar replicar esse problema apenas executando muitas E / S de arquivos fictícios do espaço do usuário enquanto o aplicativo principal está em execução.

Existe uma maneira de forçar (simular) um "congelamento" global do kernel do Linux (em particular, parar o PCIe ou todos os acessos à memória DDR3 ou algo parecido) para que possamos reproduzir esse problema?

Temos buffer de até 10 milissegundos implementados agora na memória FPGA interna, mas isso não é suficiente. Podemos fazer buffer para o FPGA DDR3 e depois fazer o dump para o host, mas precisamos de um método para testar esse novo recurso sob pressão.

Não queremos que o kernel congele ou bloqueie permanentemente. Gostaríamos da capacidade de definir o intervalo de tempo.

Estou procurando algo parecido com escrever valores mágicos /proc/sys/vmtemporariamente que faça o sistema praticamente rastejar e depois voltar depois de algumas centenas de milissegundos, mas observar o número de maneiras possíveis de quebrá-lo não é para um novato como eu ( https://www.kernel.org/doc/Documentation/sysctl/vm.txt ). Talvez alguma numactlmágica?

Mark Lakata
fonte
Meu palpite é que isso requer a gravação de um módulo do kernel. Você precisará congelar todos os threads em todas as CPUs de alguma forma e organizar a reinicialização em uma interrupção do timer.
Gilles 'SO- stop be evil'
Não quero congelar os threads, quero congelar o kernel! Quero dizer, quero impedir o acesso ao hardware (memória e / ou PCIe e / ou disco) por um curto período de tempo. Se isso não funcionar, não me importo de tornar as coisas muito otimizadas, desativando o cache L1 etc. Apenas não sei como fazer isso.
Mark Lakata
1
Ah, então você não deseja congelar o kernel, apenas deseja congelar a parte do kernel que responde a algum hardware? Isso também exigiria mergulhar profundamente no núcleo.
Gilles 'SO- stop be evil'
Não me importo de congelar o kernel completamente, desde que o hardware esteja congelado como parte dele.
Mark Lakata
1
Acontece que o problema está relacionado ao thrashing TLB à medida que a CPU host libera alguns buffers de E / S (estamos usando o HDF5 para gravar arquivos), e esse thrashing TLB está fazendo com que o coprocessador também thrash, pois é um sistema NUMA. Acho que tudo o que precisamos agora é uma maneira confiável de causar programaticamente o TLB thrashing por um período controlado.
precisa saber é o seguinte

Respostas:

9

Uma opção para fazer um teste rápido pode ser usar um kernel habilitado para KGDB e parar o kernel manualmente e testar, consulte este link .

Em outra nota, lembro-me de coisas que poderiam causar suas pausas:

  • cpufreq,, cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_transition_latencyo valor está em ns (4000 no meu processador AMD FX (tm) -8120 de oito núcleos) não deve ser um problema, mas verifique
  • Regulagem térmica tanto da própria CPU quanto do módulo regulador de tensão.
  • NAPI e / ou tráfego intenso da rede
  • ASPM PCIe ( cat /sys/module/pcie_aspm/parameters/policy)
  • Contenção nos buffers do seu dispositivo de destino (disco rígido, nic ...)
  • Bug no firmware de algum dispositivo no barramento PCIe (mesmo se você não o estiver usando), você pode tentar desligá-los com /sys/bus/pci/devices/$DEVICE/power/control
Jorge Nerín
fonte
Eu poderia usar em kdbvez de kgdbfazer o mesmo? Eu também nunca usei. É como a sequência de comandos "Stop-A" nas estações de trabalho da Sun no passado? Se eu fizer um SysRq-g rápido e digitar "go", terei uma alta probabilidade de não interromper o sistema? (ref: kernel.org/pub/linux/kernel/people/jwessel/kdb/… )
Mark Lakata
1
Provavelmente você poderá usar o kdb. Esteja ciente de que ele deve funcionar com teclados conectados por USB, mas tente ter um PS / 2 à mão, apenas por precaução. E este é um depurador de nível muito baixo (terra do kernel), portanto, como sempre, mantenha os backups e, se quebrar, você poderá manter as duas partes :).
Jorge Nerín
Antes de recorrer ao aprimoramento com o kernel, primeiro tentava descarregar módulos do kernel não utilizados para dispositivos PCIe que poderiam estar usando o barramento (principalmente os drivers gráficos) e remover fisicamente os dispositivos do sistema ou desligá-los. O PCIe 1.0 x1 tem uma largura de banda de 250 MB / se o PCIe 2.0 x1 sobe para 500 MB / s, o dispositivo de origem e destino está livre para aceitar essa taxa sustentada sem interrupções ou eles têm mais faixas para permitir mais espaço?
Jorge Nerín
Outra fonte possível do atraso pode ser algum manipulador de gerenciamento de energia ACPI de algum dispositivo ou talvez até algum manipulador de CPU SMM aguardando um evento externo.
27414 Franki
2

Podemos ter mais detalhes sobre como seu aplicativo está se comunicando com o FPGA? É o aplicativo que lê o buffer do FPGA ou do FPGA que envia interrupção para o kernel (como placas de rede)?

Espero que abra um bloco / char em / dev e depois comunique-se com ele. Isso significa que ele usa um driver para fazer a comunicação entre o aplicativo e o arquivo / dev / XXX.

Eu gostaria de ter a saída de cat /proc/interrupts:; lsmod;ls -al /dev/yourmod

Aqui estão as idéias:

  • Se for acionado por interrupção, você poderá definir o PIC da CPU para desativar o IRQ correspondente e reativá-lo. Isso fará com que todas as solicitações do cartão sejam ignoradas (sem que o cartão esteja ciente disso).
  • se for como uma leitura de buffer, você pode:
    • Coloque seu aplicativo no estado de suspensão, para que os dados do FPGA não sejam lidos, e seu buffer seja preenchido. Em seguida, ative seu aplicativo e continue a leitura.
    • Use "crash" ou "kgdb" para alterar o valor "read" para "noop" por alguns segundos e, em seguida, retorne à função padrão.

Forneça todas as informações que você achar úteis.

Adrien M.
fonte
O FPGA faz DMA grava na memória do host e, durante esses períodos de interrupção, o FPGA não pode gravar na memória do host, portanto, o backup FIFO interno é feito. Há uma interface baseada em mensagens para o processo host (acontece no PCIe), mas estou certo de que isso não está envolvido. Para fins de validação, basicamente preciso de uma maneira de proibir que o hardware FPGA grave na memória do host por algumas centenas de milissegundos. Não quero resolver o problema de memória, mas quero garantir que nossa implementação no FPGA seja capaz de lidar com uma falta de memória (até 1000 ms).
Mark Lakata
Ok, se estiver usando o DMA, você pode dar uma olhada em: kernel.org/doc/Documentation/DMA-ISA-LPC.txt, em particular no claim_dma_lock () e dma_disable (). No entanto, você precisará conhecer os endereços usados ​​pelo seu FPGA.
Adrien M.
1

Não tenho certeza se isso ajuda. Mas se você pode escrever um módulo do kernel que chama a suspendfunção do módulo do kernel de outro dispositivo, isso pode acontecer.

Cada dispositivo PCI pode ser suspenso de acordo com o arquivo de cabeçalho http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/pci.h#L479

Por exemplo, aqui está a função de suspensão da Intel e1000 NIC http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/e1000e/netdev.c#L4643

Pelo que me lembro, essa função foi usada principalmente quando o sistema entra em hibernação, o driver de dispositivo precisa salvar o status atual de execução e desligar-se.

yegle
fonte
obrigado, mas acho que não vai funcionar. Eu realmente não quero suspender um dispositivo, que é o kernel que diz ao dispositivo para se preparar para a hibernação; Quero que o kernel ignore o dispositivo específico (neste caso, a placa filha FPGA) sem ele saber (além de longas latências ou tempos limite) - ou desejo interromper todas as transferências de memória SDRAM.
MarkLakata
0

Eu acho que você está pensando na linha errada. Seu objetivo é claro.

O caminho não é interromper o restante dos processos, mas dar prioridade aos seus processos principais em tempo real. Use bom para seus processos importantes de espaço do usuário para isso.

O problema mais difícil é o tratamento de interrupções do PCIe, que reside no espaço do kernel.

Como o hardware está envolvido, você deve começar a olhar mais de perto a pista PCIe envolvida na sua placa principal e como isso está possivelmente conectado a um soquete da CPU específico.

O irqbalance normalmente faz um bom trabalho aqui, mas você pode configurar seu comportamento para atender às suas necessidades.

Nils
fonte