3 pontos por GN⁺ 2025-08-08 | 1 comentários | Compartilhar no WhatsApp
  • Este artigo se concentra no desenvolvimento do driver de GPU de kernel para Linux mais moderno, Tyr, desenvolvido em Rust, e no princípio de funcionamento de drivers de GPU
  • Na criação de drivers de GPU, explica-se a distinção de papéis e a interação entre UMD (User Mode Driver) e KMD (Kernel Mode Driver) por meio do exemplo VkCube
  • A UMD converte APIs de alto nível em comandos de baixo nível compreensíveis pela GPU, enquanto o KMD é responsável por funções centrais, como alocação de memória, escalonamento de trabalhos e inicialização do dispositivo
  • A API fornecida pelo driver Tyr é a mesma do Panthor e inclui consulta de dispositivo, gerenciamento de memória, gerenciamento de grupos, submissão de trabalhos e gerenciamento do heap de Tiler, entre outros
  • No próximo texto, serão tratados a arquitetura de hardware Arm CSF e seus componentes principais (como a MCU), além do processo de inicialização

Introdução: desenvolvimento de driver de kernel GPU moderno baseado em Rust

  • Este artigo é o segundo da série de desenvolvimento do driver de kernel GPU Tyr, de ponta para GPUs Arm Mali baseadas em CSF no Linux
  • Como exemplo prático, escolheu-se o VkCube, um programa simples de 3D que renderiza um cubo giratório usando a Vulkan API, para explicar como funciona o interior de um driver de GPU
  • A estrutura simples do VkCube é adequada para estudar os princípios de funcionamento de drivers de GPU

Fundamentos de driver de GPU: função e estrutura de UMD e KMD

  • É composto por User Mode Driver (UMD) e Kernel Mode Driver (KMD)
    • UMD: implementa APIs de programas comuns, como panvk (driver Vulkan do Mesa)
    • KMD: como Tyr, é o driver privilegiado em nível de kernel do hardware e opera como parte do kernel do Linux
  • O driver de GPU em modo kernel faz a ponte entre a UMD e a GPU real; a UMD interpreta comandos de API e os converte em conjuntos de comandos entendíveis pelo hardware
  • A UMD prepara dados necessários para montar a cena, como geometria, textura e shaders, e solicita ao KMD a alocação desses dados na memória da GPU antes da execução
  • Shader é um programa independente que roda na GPU; no VkCube, ele é responsável por posicionar o cubo, aplicar cores e implementar a rotação. A execução do shader depende de dados externos (geometria, cor, matriz de rotação etc.)
  • A UMD envia os comandos preparados (por exemplo, VkCommandBuffers) ao KMD para execução e, ao concluir, recebe a notificação para gravar o resultado na memória

Principais responsabilidades do KMD (Kernel Mode Driver)

  • Alocação e mapeamento da memória da GPU (fornecendo isolamento por aplicação)
  • Submissão de tarefas para as filas de hardware e notificação ao usuário no momento de conclusão
  • Em ambientes de hardware assíncrono e paralelo, o gerenciamento de dependências é essencial, e para garantir resultados corretos o KMD desempenha o papel de escalonamento e validação de dependências
  • Também inclui inicialização do dispositivo, operação de reguladores de clock/tensão, execução de código de inicialização e gerenciamento da rotação de acesso para que múltiplos clientes compartilhem o hardware de forma justa

Onde está a complexidade: divisão de trabalho entre UMD e KMD

  • A complexidade do driver de GPU está concentrada principalmente na UMD
    • UMD: converte comandos de API de alto nível em comandos de hardware
    • KMD: oferece funcionalidades essenciais para a UMD operar corretamente, como isolamento de memória, compartilhamento e acesso justo

Estrutura da interface de driver (API) fornecida pelo Tyr

  • A API do driver Tyr (= igual ao Panthor) pode ser dividida em 5 grupos principais
    1. Consulta de informações do dispositivo: DEV_QUERY (consulta de informações de hardware da GPU via IOCTL, uso da área ROM)
    2. Alocação e isolamento de memória: VM_CREATE, VM_BIND, VM_DESTROY, VM_GET_STATE, BO_CREATE, BO_MMAP_OFFSET
    3. Gerenciamento de grupos de escalonamento: GROUP_CREATE, GROUP_DESTROY, GROUP_GET_STATE (detalhes serão abordados em artigo futuro)
    4. Submissão de trabalhos: GROUP_SUBMIT (pedido de execução da GPU por meio de command buffers do dispositivo)
    5. Gerenciamento de heap de Tiler: TILER_HEAP_CREATE, TILER_HEAP_DESTROY (atende requisitos de memória para GPUs de renderização por tiling)
  • Essas APIs ficam distantes das operações de desenho de imagem em si; a UMD é quem executa os comandos reais, enquanto o KMD disponibiliza apenas esta interface para acesso ao hardware

Conclusão e próximos passos

  • Neste texto, examinamos a estrutura e o fluxo interno geral de drivers de GPU e as principais APIs fornecidas pelo Tyr
  • Com base nesse conteúdo, nos próximos textos da série serão tratados a arquitetura de hardware Arm CSF, o microcontrolador (MCU) e demais componentes centrais, além do processo de inicialização do driver

1 comentários

 
GN⁺ 2025-08-08
Comentário no Hacker News
  • Era um texto realmente bom, mas ficou curto demais; parecia que começava a ficar interessante e já tinha acabado. Vou ficar no aguardo do próximo capítulo.
    • Também vai ter um novo episódio na semana que vem, e vamos conseguir ver os comandos pendentes saindo da fila da GPU e sendo executados. O nível de abstração abordado neste texto é basicamente a passagem de dados na fronteira usuário/_kernel, então ele trata basicamente de gerenciamento de fila e buffer e quase não entra em operação de fato; o ponto realmente importante acontece quando os comandos enfileirados começam a ser executados. Ainda fico curioso para ver como outro sinal de conclusão do comando é enviado de volta pela GPU no sentido inverso. Quase todo esse processamento assíncrono fica do lado do código de usuário, não do driver; o driver só repassa o sinal de conclusão.
  • Eu uso um dos dispositivos RK3588 como desktop com panfrost, e às vezes acontece de o Firefox exibir a tela preta ou com áreas transparentes, algo estranho.
    • O RK3588 na prática usa o driver panthor, que é justamente o tema deste texto, e não panfrost.
  • Fiquei curioso se a alternativa de usar uring_cmd em vez de ioctls foi considerada, já que esse projeto pareceu viável por ser feito do zero; fiquei curioso de saber por que você achou que a vantagem é quase inexistente.
    • Como a GPU já tem sua própria fila de comandos assíncrona, o IOCTL já desempenha por si só o papel de gravar nessa fila com custo relativamente baixo; portanto, criar outra fila assíncrona no lado da CPU só para agendar essa escrita é uma escolha com utilidade limitada. Se a sugestão for transformar a própria fila de comandos da GPU em uma uring mapeada no userspace, então para dar suporte adequado à especificação da API do io_uring seria preciso mexer bastante no firmware, e pode ser até impossível por causa das características de hardware.
    • O driver descrito no artigo segue a API exigida pela biblioteca Mesa em userspace.
  • Li com muito interesse e fiquei curioso para ver se haverá uma sequência ou algo que avance de forma lógica.
    • Como o artigo foi publicado hoje pela primeira vez, espero que venham atualizações depois.
  • Entendo que o título "Rust GPU driver" é mais chamativo, mas na prática isso não é um driver de GPU baseado em Arm Mali CSF? Pessoalmente, esse foco numa meta-ferramenta para desenvolvimento de ferramentas não me agrada; soa como se o objetivo real fosse construir algo em Rust. O texto chama isso de "kernel de driver de GPU baseado no arm mali" e, ainda assim, evita chamar de driver arm mali. Para mim, fazer um driver é simplesmente conectar a API do sistema operacional à API do fabricante de hardware, não criar uma estrutura de abstração adicional com um framework em cima. Perdão se pareço direto.
    • A relevância do Rust aqui é que este é um dos primeiros (ou talvez o primeiro) casos no Linux de uso da infraestrutura Rust em drivers de GPU.
    • Não leve a mal meu jeito bruto, mas pelo seu tom parece que você não tem ideia do que é um driver de GPU moderno. Eu já tinha usado isso há uns 15 anos, e sei que desde então ficou ainda mais complexo; basta olhar para o código-fonte do kernel Linux para ver que os drivers de GPU já ocupam a maior parte em linhas de código. Quase todos os drivers dão suporte a várias placas de vídeo, então não sei se faz sentido criar um driver totalmente independente do zero para cada GPU individualmente. Trabalho com driver de GPU não é só 'ligar uns pontos' entre duas APIs; na prática é bem mais diferente. Se quiser discutir, mostre um driver de GPU que você tenha escrito; eu quero ver se foi realmente só conectar alguns pontos e pronto.
    • O Rust é importante aqui porque se trata de uma das primeiras tentativas de usar infraestrutura Rust em driver de GPU no Linux.