AFAIKは、/dev/mem
ユーザーに物理メモリを提供し、通常、MMIOを介したデバイスの読み取り/書き込みに使用されます。私のユースケースでは、2つのpteが同じ物理ページを指すように、現在のプロセスのpteを変更したいと思います。特に、x86_64バイナリを4G仮想空間の上に移動し、mmap仮想空間を4Gの下に移動します。pteより上の4Gとpteより下の4Gが同じ物理ページを指すようにしたいので、vaddrより上の4Gに書き込み、pteより下の4Gから読み取ると、同じ結果が得られます。サンプルコードは次のようになります。
*(unsigned char *)vaddr1 = 7 // write into 4G above vaddr1
val = *(unsigned char *)vaddr2; // read from 4G below vaddr2
printf("val should be 7, %d\n", val);
しかし、pteの下の4Gを変更して、pteの上の4Gが指す物理ページを指すようにする/dev/mem
と、カーネルは以下のメッセージを表示します。
BUG: Bad page map in process mmap pte:8000000007eb2067 pmd:07acb067
page:ffffea00001fac80 count:0 mapcount:-1 mapping: (null) index:0x101b7b
page flags: 0x4000000000000014(referenced|dirty)
addr:0000000101b7b000 vm_flags:00100073 anon_vma:ffff880007ab0708 mapping: (null) index:101b7b
Pid: 609, comm: mmap Tainted: G B 3.5.3 #7
Call Trace:
[<ffffffff8107abcc>] ? print_bad_pte+0x1d2/0x1ea
[<ffffffff8107bf18>] ? unmap_single_vma+0x3a0/0x56d
[<ffffffff8107c745>] ? unmap_vmas+0x2c/0x46
[<ffffffff8108106b>] ? exit_mmap+0x6e/0xdd
[<ffffffff8101cc4f>] ? do_page_fault+0x30f/0x348
[<ffffffff81020ce6>] ? mmput+0x20/0xb4
[<ffffffff810256ae>] ? exit_mm+0x105/0x110
[<ffffffff8103bb6c>] ? hrtimer_try_to_cancel+0x67/0x70
[<ffffffff81026b59>] ? do_exit+0x211/0x711
[<ffffffff810272e0>] ? do_group_exit+0x76/0xa0
[<ffffffff8102731c>] ? sys_exit_group+0x12/0x19
[<ffffffff812f3662>] ? system_call_fastpath+0x16/0x1b
BUG: Bad rss-counter state mm:ffff880007a496c0 idx:0 val:-1
BUG: Bad rss-counter state mm:ffff880007a496c0 idx:1 val:1
カーネルはpteが変更されているかどうかを調べると思いますが、私は何か間違ったことをしました。これが私のpte書き換えの前後のvaddr1とvaddr2のpteです。
above 4G pte: 0x8000000007eb2067
below 4G pte: 0x0000000007ea7067
after rewriting pte...
above 4G pte: 0x8000000007eb2067
below 4G pte: 0x8000000007eb2067
何か案が?ありがとう。
注:これで、vaddr2のpteが指す物理ページを解放する必要があることがわかりました。そうしないと、カーネルは物理ページがどのpteも指していないと認識し、エラーを出します。しかし、どのように?を使おうとして__free_page
いますが、以下のエラーが発生します。
BUG: unable to handle kernel paging request at ffffebe00008001c
IP: [<ffffffff8106b908>] __free_pages+0x4/0x2a
PGD 0
Oops: 0000 [#2] PREEMPT SMP
CPU 0