2

Linuxソースコード(バージョン2.6.18)の場合:

movl $swapper_pg_dir-__PAGE_OFFSET,%eax
movl %eax,%cr3
movl %cr0,%eax
orl $0x80000000,%eax
movl %eax,%cr0          /* ..and set paging (PG) bit */
ljmp $__BOOT_CS,$1f     /* Clear prefetch and normalize %eip */

また、load_cr3(pgdir)およびwrite_cr3(x)マクロ:

#define load_cr3(pgdir) write_cr3(__pa(pgdir))

#define write_cr3(x) \
__asm__ __volatile__("movl %0,%%cr3": :"r" (x))

cr3制御レジスタ全体がページディレクトリのアドレスを格納しているようです。ただし、Intel ia-32 Developer's_Manualを参照すると、別の話になります。インテルのマニュアルには次のように書かれています。

name      0.............11   12.................31
cr3       flags              address of page directory
PDE       flags              address of page table
PTE       flags              address of 4kb page frame

マニュアルによると、最上位20ビットはレジスタcr3全体ではなくページディレクトリのアドレスを格納しますcr3。また、ページディレクトリが正確に4kbであるため、アドレスの最下位12ビットは常にゼロであるため合理的です。

ちょっと変じゃないですか?cr3Linuxコードは、の最上位20ビットではなく、ページディレクトリのアドレスを割り当てるだけswapper_pg_dirです。レジスターは正確に何cr3を保存しますか、インテルのマニュアルが示唆するアドレスまたはフォーマットは何ですか?

次のリンクはIntelのマニュアルです:http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html

4

2 に答える 2

4

32ビットページングの場合、ページディレクトリのアドレスは4096の倍数である必要があります。つまり、その12LSBはゼロです。ただし、cr3を設定するためのオペコードは20ビットではなく32ビットをロードします。cr3がロードされると、その上位20ビットがページディレクトリアドレスに使用され、下位12ビットはフラグとして解釈されます。これは新しいプロセッサバージョンのページング動作に影響を与える可能性があります。これらのフラグの「安全な」設定はゼロであり、これはまさにLinuxが行うことです。cr3に32ビット値をロードします。これはたまたま12LSBがゼロに等しいためです(32ビット値がメモリとして使用されているため)。 4096の倍数であるアドレス)。

于 2011-10-27T11:49:14.240 に答える
2

swapper_pg_dir-__PAGE_OFFSET4096の倍数であれば、何も奇妙なことはありません。

CR3LSBのゼロは有効です。

  • 予約ビットは0に設定する必要があります
  • 新しい(i80386以降)機能は、関連するビットも0に設定することで無効にできます。これは、通常、x86CPUと古いソフトウェアとの下位互換性を維持する方法です。
于 2011-10-27T11:36:28.440 に答える