El mapa de páginas en dispositivos asignados en memoria no funciona

El mapa de páginas en dispositivos asignados en memoria no funciona

Estoy tratando de encontrar las direcciones físicas de las variables del montón, las variables de la pila y las direcciones periféricas asignadas en memoria usando el archivo /proc/{pid}/pagemap siguiendo los pasos detallados en el archivo:http://lxr.free-electrons.com/source/Documentation/vm/pagemap.txt. El procedimiento detallado funciona bien para variables de pila y montón. Sin embargo, para los periféricos asignados en memoria no se encuentra ninguna página en el archivo /proc/{pid}/pagemap. La salida de 'cat /proc/{pid}/maps' es:

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]

Cuando intento encontrar las direcciones físicas de 0x00013000 o 0xbee36000, funciona bien. Sin embargo, el archivo de mapa de páginas no devuelve ninguna página encontrada cuando intento encontrar la dirección física correspondiente a 0xb2efe000 que pertenece a /dev/uio0. Estoy intentando hacer esto con fines de verificación. Sé que existe una dirección física porque usé mmap en 0x1b90000 ignorado para encontrar 0xb2efe000. ¿Alguien podría explicar por qué el archivo /proc/{pid}/pagemap no contiene la dirección física?

Respuesta1

Respuesta corta: La interfaz del mapa de páginas expone información almacenada en la página de estructura asociada con la dirección. Las direcciones de E/S son asignaciones pfn sin formato sin una página de estructura asociada y, por lo tanto, se exponen como ceros.

respuesta más larga La reasignación de direcciones físicas (incluidas las direcciones de E/S) al espacio de usuario se realiza llamando a remap_pfn_range. Estas direcciones reasignadas no tienen ningún struct pageasociado (son asignaciones pfn sin formato). Para recordar que estas direcciones son especiales, esta función se configura VM_PFNMAPen el vma.

La interfaz del mapa de páginas expone un montón de campos que tienen que ver con lo que está struct pageasociado con la dirección. Pero no existe tal estructura para estas direcciones. Entonces el mapa de páginas simplemente los omite:

Cuando se utiliza el mapa de páginas, el núcleo recorre la página utilizando walk_page_range. Los vmas etiquetados con VM_PFNMAPse tratan de manera 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).
 */

pte_hole de pagemap simplemente coloca un montón de entradas cero (módulo, algún indicador adicional para VM_SOFTDIRTY). Por eso no lo ves...

No conozco ninguna interfaz del kernel que le permita recuperar la dirección física para tales asignaciones. Pero sería fácil hacerlo con un módulo del kernel o usando crash.

información relacionada