UEFI経由で起動する、単純な自家製の64ビットOSを作成しています。これは、私のコードが実行を開始したときに、ページングが有効になっているロング モードになっていることを意味します。
ここで、UEFI ブート サービスを終了した後、UEFI によって構築されたすべての制御構造を独自のものに置き換えたいと考えています。
CR3 (ページング構造) の内容を正常に変更した後、 を使用して新しい GDT を正常にロードしましたlgdt
。
問題は、この新しい GDT を正しく使用するには、新しい値を CS に移動する必要があることです。オンラインでは、32 ビットから 64 ビットに切り替える際にそれを行う方法に関するチュートリアルがたくさん見つかりましたが、ロング モードからロング モードへの切り替えについてはほとんど何もありませんでした。
ファージャンプを使用する必要があると思いますが、このコード (AT&T 構文) ではそれを行うことができませんでした:
mov %rax, %cr3 # load paging structures (it works)
lgdt 6(%rcx) # load gdt (it works)
mov $100, %rsp # update stack pointer (it works)
# now what I tried unsuccessfully:
pushw $8 # new code segment selector
pushq fun # function to execute next
retfq # far return (pops address and code segment)
IDT が設定されていないため、このコードは でトリプル フォールトしretfq
ます。
編集:ページング構造を確認しましたが、それらが問題の原因ではないと確信しています。実際、コードは最後の 3 つの命令がなくても正常に実行されます。問題は、私のコードでは UEFI によって構築された古いセグメントをまだ参照している CS を更新する方法が必要なことです。retfq
これを行う正しい方法はありますか?または、他のどの命令を使用する必要がありますか?
前もって感謝します。