2

私は自分のオペレーティング システム プロジェクトに取り組んでいます。スターター コードは既にロング モードにジャンプし、一時ページ テーブルをセットアップします。これで、自分のページテーブルをセットアップして埋め、必要な方法でメモリのマッピングを完了しました。ここで、CR3 レジスタに PML4T の物理アドレスを設定する必要があります。

238 void setcr3(void * addr){
239 uint64_t temp=(uint64_t)addr;
240
241   __asm__ ("movq %0, %%cr3;"::"b"(temp));
242 }

これは、その命令の実行中にクラッシュします。GDB ステップバイステップ添付

0x0000000000000000 in ?? ()
(gdb) b setcr3
Breakpoint 1 at 0xffffffff80201205: file sys/paging.c, line 238.
(gdb) c
Continuing.

Breakpoint 1, setcr3 (addr=0x221000) at sys/paging.c:238
238     void setcr3(void * addr){
(gdb) si
241       __asm__ ("movq %0, %%cr3;"::"b"(temp));
(gdb) si
0xffffffff80201209      241       __asm__ ("movq %0, %%cr3;"::"b"(temp));
(gdb) si
242     }
(gdb) si
Remote connection closed
(gdb)
244 #define write_cr3(x) \
245 __asm__ __volatile__("movl %0,%%cr3": :"r" (x))


Error while compiling

sys/paging.c: Assembler messages:
sys/paging.c:271: Error: unsupported instruction `mov'

編集:

printf("address in cr3 %x\n", (uint64_t)pml4t - 0xffffffff80200000 + physbase);
setcr3( (void *) ( (uint64_t)pml4t - 0xffffffff80200000 + physbase) );


line 1 prints:
address in cr3 221000
4

2 に答える 2

0

asm ("movq %0, %%cr3;"::"b"(temp));

「b」の代わりに「r」を使用することをお勧めします。これにより、値を移動するために使用するレジスタをコンパイラが処理し、命令の実行後に値を復元できるようになります。

asm volatile ("movl %0,%%cr3": :"r" (x));

movl の代わりに movq を使用します。

setcr3( (void *) ( (uint64_t)pml4t - 0xffffffff80200000 + 物理ベース) );

カーネルで初めてページ テーブルを設定する場合、物理アドレスを cr3 レジスタに渡すために、pml4t の仮想アドレスから 0xffffffff80200000 を差し引くだけで済みます。physbase を追加する必要はありません。これは、カーネルの elf セクションをロードした後、メモリ内で最初に使用可能なアドレスを取得している可能性があるためです。

最後に、コンパイラが命令を最適化しないように、asm ブロックの前に volatile を追加することをお勧めします。また、型キャストを回避するには、マクロの代わりに以下の行を直接使用して、何が起こるかを確認してください。

asm volatile ("movq %[cr3_var], %%cr3;"::[cr3_var]"r"((uint64_t)pml4t));

于 2015-04-18T10:39:51.690 に答える