Pagemap em dispositivos mapeados na memória não funciona

Pagemap em dispositivos mapeados na memória não funciona

Estou tentando encontrar os endereços físicos de variáveis ​​de heap, variáveis ​​de pilha e endereços periféricos mapeados na memória usando o arquivo /proc/{pid}/pagemap usando as etapas detalhadas no arquivo:http://lxr.free-electrons.com/source/Documentation/vm/pagemap.txt. O procedimento detalhado funciona bem para variáveis ​​de pilha e heap. No entanto, para periféricos mapeados em memória, nenhuma página é encontrada no arquivo /proc/{pid}/pagemap. A saída de 'cat /proc/{pid}/maps' é:

00008000-0000a000 r-xp 00000000 b3:02 289852     /home/linaro/ocm_test/write-memory
00011000-00012000 r--p 00001000 b3:02 289852     /home/linaro/ocm_test/write-memory
00012000-00013000 rw-p 00002000 b3:02 289852     /home/linaro/ocm_test/write-memory
00013000-00034000 rw-p 00000000 00:00 0          [heap]
b2efe000-b6dfe000 rw-s 00001000 b3:02 284849     /dev/uio0
b6dfe000-b6ed2000 r-xp 00000000 b3:02 282416     /lib/arm-linux-gnueabihf/libc-2.15.so
b6ed2000-b6eda000 ---p 000d4000 b3:02 282416     /lib/arm-linux-gnueabihf/libc-2.15.so
b6eda000-b6edc000 r--p 000d4000 b3:02 282416     /lib/arm-linux-gnueabihf/libc-2.15.so
b6edc000-b6edd000 rw-p 000d6000 b3:02 282416     /lib/arm-linux-gnueabihf/libc-2.15.so
b6edd000-b6ee0000 rw-p 00000000 00:00 0 
b6ee0000-b6ee2000 r-xp 00000000 b3:02 27519      /usr/lib/libinterface.so
b6ee2000-b6ee9000 ---p 00002000 b3:02 27519      /usr/lib/libinterface.so
b6ee9000-b6eea000 r--p 00001000 b3:02 27519      /usr/lib/libinterface.so
b6eea000-b6eeb000 rw-p 00002000 b3:02 27519      /usr/lib/libinterface.so
b6efb000-b6f12000 r-xp 00000000 b3:02 282407     /lib/arm-linux-gnueabihf/ld-2.15.so
b6f13000-b6f14000 rw-p 00000000 00:00 0 
b6f14000-b6f15000 rw-s 00000000 b3:02 284849     /dev/uio0
b6f15000-b6f19000 rw-p 00000000 00:00 0 
b6f19000-b6f1a000 r--p 00016000 b3:02 282407     /lib/arm-linux-gnueabihf/ld-2.15.so
b6f1a000-b6f1b000 rw-p 00017000 b3:02 282407     /lib/arm-linux-gnueabihf/ld-2.15.so
bee36000-bee57000 rw-p 00000000 00:00 0          [stack]
bef1f000-bef20000 r-xp 00000000 00:00 0          [sigpage]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

Quando tento encontrar os endereços físicos de 0x00013000 ou 0xbee36000, funciona bem. No entanto, o arquivo de mapa de páginas não retorna nenhuma página encontrada quando tento encontrar o endereço físico correspondente a 0xb2efe000 que pertence a/dev/uio0. Estou tentando fazer isso para fins de verificação. Eu sei que existe um endereço físico porque usei mmap em 0x1b90000 ignorado para encontrar 0xb2efe000. Alguém poderia explicar por que o arquivo /proc/{pid}/pagemap não contém o endereço físico?

Responder1

Resposta curta: a interface pagemap expõe informações armazenadas na página struct associada ao endereço. Endereços de E/S são mapeamentos pfn brutos sem uma página struct associada e, portanto, são expostos como zeros.

Resposta mais longa O remapeamento de endereços físicos (incluindo endereços de E/S) para o espaço do usuário é feito chamando remap_pfn_range. Esses endereços remapeados não possuem um struct pageassociado a eles (são mapeamentos pfn brutos). Para lembrar que esses endereços são especiais, esta função é configurada VM_PFNMAPno vma.

A interface do pagemap expõe vários campos que têm a ver com o que está struct pageassociado ao endereço. Mas não existe tal estrutura para esses endereços. Então o pagemap simplesmente os ignora:

Quando o pagemap é usado, o kernel percorre a página usando walk_page_range. vmas marcados com VM_PFNMAPsão tratados de forma diferente:

/*
 * vma(VM_PFNMAP) doesn't have any valid struct pages behind VM_PFNMAP
 * range, so we don't walk over it as we do for normal vmas. However,
 * Some callers are interested in handling hole range and they don't
 * want to just ignore any single address range. Such users certainly
 * define their ->pte_hole() callbacks, so let's delegate them to handle
 * vma(VM_PFNMAP).
 */

O pte_hole do pagemap apenas coloca um monte de entradas zero (módulo algum sinalizador adicional para VM_SOFTDIRTY). É por isso que você não vê...

Não conheço nenhuma interface do kernel que permita recuperar o endereço físico para tais mapeamentos. Mas seria fácil fazer isso com um módulo do kernel ou usando o crash.

informação relacionada