Acesso à memória compartilhada de E/S do Linux

Acesso à memória compartilhada de E/S do Linux

Estou bastante confuso sobre como o Linux gerencia a memória compartilhada de E/S para se comunicar com os dispositivos que o utilizam.

Se bem entendi, o kernel do Linux inicia mapeado em 0x100000 (para evitar os primeiros dados de memória RAM herdados de megabyte e ser armazenado em locais de memória contíguos) e depois de entrar no modo protegido:

  • em sistemas de 32 bits há um mapeamento como este

insira a descrição da imagem aqui

O ZONE_NORMAL deve estar abaixo de 896 MB, portanto o mapeamento entre os 1GB lineares do kernel e os 896 MB físicos é sempre possível. Vamos ignorar ZONE_DMA por enquanto (li que isso é apenas para sistemas legados, já que o PCI agora pode usar transferências DMA em qualquer lugar da memória)

  • em sistemas de 64 bits, o espaço de endereço linear do kernel deve começar em PAGE_OFFSET= 0xffff810000000000 e adiante

Em ambos os casos, se um endereço no espaço do kernel for maior que PAGE_OFFSET, deverá referir-se a um mapeamento ioremap (a ser resolvido através de paginação), se for menor que PAGE_OFFSET poderá ser resolvido com um simples NEW_ADDRESS = OLD_ADDRESS - PAGE_OFFSET. Isso está correto?

Pergunta bônus: quando o kernel está instalado e funcionando e a organização foi feita, ele ainda reside fisicamente de 0x100000 em diante (dentro do primeiro GB)? Mesmo em sistemas de 64 bits?

Responder1

Em PCs, os intervalos de E/S mapeados na memória de hardware são atribuídos pelo BIOS a endereços de memória física entre 3GiB e 4 GiB. Quando um driver solicita acesso à memória, o kernel a mapeia em algum lugar no espaço de endereço virtual do kernel.

Nenhuma das suas outras duas perguntas parece ter algo a ver com memória compartilhada, mas:

Em ambos os casos, se um endereço no espaço do kernel for maior que PAGE_OFFSET, deverá referir-se a um mapeamento ioremap (a ser resolvido através de paginação), se for menor que PAGE_OFFSET poderá ser resolvido com um simples NEW_ADDRESS = OLD_ADDRESS - PAGE_OFFSET. Isso está correto?

Mentalmente, sim. O hardware usa as tabelas de páginas em ambos os casos.

Responder2

Pense na sua pergunta, como funciona o ioremap.

vaddr = ioremap(paddr_io_mapped_device, tamanho);

vaddr é o endereço virtual retornado no espaço do kernel. O kernel cria as entradas da tabela de páginas para o intervalo de endereços virtuais (vaddr , size) e mapeia-o para o endereço físico paddr_io_shared_device. Portanto, se você acessar o intervalo de endereços virtuais, será tão bom quanto acessar o endereço físico dentro do dispositivo io_mapped.

É importante ressaltar que o vaddr retornado énão armazenável em cache. Cada vez que você lê/grava o intervalo de endereços, ele será lido/gravado no dispositivo io_mapped e não no cache.

informação relacionada