Pagemap на устройствах с отображением памяти не работает

Pagemap на устройствах с отображением памяти не работает

Я пытаюсь найти физические адреса переменных кучи, переменных стека и периферийных адресов, отображенных в памяти, с помощью файла /proc/{pid}/pagemap, следуя шагам, подробно описанным в файле:http://lxr.free-electrons.com/source/Documentation/vm/pagemap.txt. Описанная процедура хорошо работает для переменных стека и кучи. Однако для отображенных в память периферийных устройств страница не найдена в файле /proc/{pid}/pagemap. Вывод '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]

Когда я пытаюсь найти физические адреса 0x00013000 или 0xbee36000, все работает нормально. Однако файл карты страниц возвращает сообщение о том, что страница не найдена, когда я пытаюсь найти физический адрес, соответствующий 0xb2efe000, который принадлежит /dev/uio0. Я пытаюсь сделать это в целях проверки. Я знаю, что физический адрес существует, потому что я использовал mmap на 0x1b90000, проигнорированном, чтобы найти 0xb2efe000. Может ли кто-нибудь объяснить, почему файл /proc/{pid}/pagemap не содержит физического адреса?

решение1

Короткий ответ: Интерфейс pagemap предоставляет информацию, хранящуюся в странице структуры, связанной с адресом. Адреса ввода-вывода являются необработанными отображениями pfn без связанной страницы структуры и поэтому отображаются как нули.

Более длинный ответ Переназначение физических адресов (включая адреса ввода-вывода) в пользовательское пространство выполняется вызовом remap_pfn_range. Эти переназначенные адреса не имеют struct pageсвязанных с ними (это необработанные отображения pfn). Чтобы помнить, что эти адреса являются специальными, эта функция устанавливает VM_PFNMAPна vma.

Интерфейс pagemap выставляет кучу полей, которые связаны с тем, что находится в struct pageсвязанном с адресом. Но для этих адресов нет такой структуры. Поэтому pagemap просто пропускает их:

При использовании pagemap ядро ​​выполняет обход страницы с использованием walk_page_range. vmas, помеченные тегом, VM_PFNMAPобрабатываются по-разному:

/*
 * 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 pagemap просто помещает кучу нулевых записей (по модулю некоторого дополнительного флага для VM_SOFTDIRTY). Вот почему вы его не видите...

Я не знаю ни одного интерфейса ядра, который позволяет извлекать физический адрес для таких отображений. Но это было бы легко сделать с помощью модуля ядра или с помощью crash.

Связанный контент