メモリマップされたデバイスのページマップが機能しない

メモリマップされたデバイスのページマップが機能しない

/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 の物理アドレスを見つけようとすると、正常に動作します。ただし、/dev/uio0 に属する 0xb2efe000 に対応する物理アドレスを見つけようとすると、ページ マップ ファイルはページが見つからないと返します。これは検証目的で実行しています。0x1b90000 を無視して mmap を使用して 0xb2efe000 を見つけたので、物理アドレスが存在することはわかっています。/proc/{pid}/pagemap ファイルに物理アドレスが含まれていない理由を説明していただけませんか?

答え1

短い答え: ページマップ インターフェイスは、アドレスに関連付けられた構造体ページに格納されている情報を公開します。I/O アドレスは、関連付けられた構造体ページを持たない生の pfn マッピングであるため、ゼロとして公開されます。

より長い回答 物理アドレス (I/O アドレスを含む) をユーザー空間に再マッピングするには、 を呼び出しますremap_pfn_range。これらの再マッピングされたアドレスには が関連付けられていませんstruct page(これらは raw pfn マッピングです)。これらのアドレスが特別であることを思い出すために、この関数はVM_PFNMAPvma をオンに設定しています。

ページマップ インターフェースは、アドレスに関連付けられている内容に関連する一連のフィールドを公開しますstruct page。ただし、これらのアドレスにはそのような構造体はありません。そのため、ページマップはそれらをスキップします。

ページマップが使用される場合、カーネルは を使用してページウォークを実行しますwalk_page_range。 でタグ付けされた vmasVM_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 は、ゼロ エントリを多数配置するだけです ( の追加フラグを除いた値VM_SOFTDIRTY)。これが表示されない理由です...

このようなマッピングの物理アドレスを取得できるカーネル インターフェイスは知りません。ただし、カーネル モジュールまたは を使用すると簡単に実行できますcrash

関連情報