Pular para o conteúdo

ACPI

O firmware sabe coisas sobre uma máquina que adivinhação não consegue recuperar: quantas CPUs ela tem, onde os I/O APICs vivem, qual segmento PCI é dono de qual faixa de barramento. ACPI é o formato que o firmware usa para repassar esse conhecimento a um sistema operacional, um conjunto de tabelas sentadas em algum lugar da memória física, esperando para serem encontradas e analisadas.

Tudo começa com a RSDP, o Root System Description Pointer. O firmware a planta em algum lugar do primeiro megabyte, ou reporta seu endereço através da tabela de configuração UEFI em máquinas que inicializam dessa forma. Um kernel encontra a cópia legada varrendo a memória em passos de 16 bytes em busca da string de assinatura "RSD PTR ", verificando um checksum, e parando na primeira correspondência. A assinatura tem oito bytes de propósito, escolhida para ser improvável de ocorrer por acidente em conteúdo comum de memória.

A própria RSDP é pequena. Seu trabalho é apontar para algo maior: a RSDT sob o esquema mais antigo de 32 bits, ou a XSDT uma vez que ponteiros de 64 bits se tornaram padrão. Ambas são arrays de mais ponteiros, um por tabela, cada um levando a uma estrutura identificada por sua própria assinatura de quatro bytes: APIC para a MADT, MCFG para o espaço de configuração PCI Express, FACP para a Fixed ACPI Description Table. Um kernel percorre esse array procurando as assinaturas de que precisa e pula o resto.

A RSDP apontando para a RSDT/XSDT, cujo array de ponteiros se ramifica para as tabelas MADT, MCFG, e FADT por assinaturaRSDP”RSD PTR “RSDT / XSDT→ APIC→ MCFG→ FACPTabelas ACPIMADT (“APIC”)CPUs, I/O APICsMCFGespaço de config PCIeFADT (“FACP”)registradores de energia

Toda tabela ACPI, seja lá o que descreva, abre com o mesmo header de 36 bytes: assinatura, comprimento, revisão, um checksum, uma string de OEM ID, e alguns outros campos identificadores. Duas coisas importam aqui. O campo de comprimento é autoritativo: uma tabela tem exatamente o comprimento que diz ter, e ler além dessa fronteira lê memória pertencente à próxima tabela ou a outra coisa. E o checksum cobre a tabela inteira, header incluído; todo byte nela soma zero módulo 256. Um kernel que pula essa verificação arrisca confiar em uma tabela que o próprio firmware consideraria inválida.

A Multiple APIC Description Table responde duas perguntas de PIC & APIC: quantos núcleos de CPU existem, e como os I/O APICs se conectam às linhas de interrupção legadas. Além de seus próprios campos fixos, a tabela é uma sequência de entradas de comprimento variável, cada uma marcada com um byte de tipo. O tipo 0 descreve um Local APIC e a CPU a que pertence. O tipo 1 descreve um I/O APIC, seu endereço-base, e a faixa de entradas de interrupção que cobre. O tipo 2 é um interrupt source override, dizendo a um kernel que algum número de IRQ legado não mapeia para a entrada de I/O APIC que um kernel ingênuo assumiria, um detalhe que importa mais do que deveria em hardware real, onde fabricantes de BIOS silenciosamente remapearam coisas por razões que raramente chegam a algum changelog.

O espaço de configuração mapeado em memória do PCI Express precisa de um endereço-base vindo de algum lugar, e a MCFG é de onde ele vem. Cada entrada nomeia um endereço-base, um número de segmento PCI, e a faixa de barramento que esse segmento cobre. Um desktop com uma host bridge tem uma entrada. Um servidor com várias pode ter mais, uma por segmento. Nada na MCFG é opcional se acesso de configuração mapeado em memória importa para um kernel: sem ela, as portas de I/O legadas são o único caminho de entrada.

Nem toda tabela ACPI é um array plano de estruturas fixas. A DSDT, e quaisquer SSDTs junto dela, contêm AML: ACPI Machine Language, um bytecode compacto descrevendo dispositivos, métodos, e estados de energia em uma forma que o firmware espera que um interpretador execute em tempo de execução. _PRT, o método de roteamento de interrupção mencionado em Entrega de interrupções, vive aqui. Assim como _ADR.

Escrever um interpretador de AML é um projeto à parte, mais próximo em escopo de um pequeno runtime de linguagem do que de um parser de tabelas. A maioria dos kernels hobby nunca tenta isso, e se vira analisando as tabelas fixas (MADT e MCFG acima de tudo) enquanto deixa a AML de lado até que suspend, resume, ou descoberta dinâmica de dispositivo de fato exijam.

  1. ^ Especificação ACPI: a definição completa dos formatos de tabela resumidos acima.
  • PIC & APIC: o hardware de interrupção que a MADT descreve.
  • PCI: o espaço de configuração que a MCFG torna mapeado em memória.
  • Reiniciando e Desligando: o registrador de reset da FADT e a dependência de AML/_S5 que a seção de AML deste artigo já sinaliza.