我正在從頭開始撰寫一個最小的 x86-64 內核,但我遇到了一些設計問題。
根據斯塔克提供的評論和鏈接,我決定重新表述我的問題。我想以 Linux 內核為例來設計我自己的內核,并希望得到一些建議。
我知道,在編譯 C 代碼時,默認情況下它將使用 RIP 相對尋址來訪問可執行檔案的資料段(對于所有全域/靜態變數)。RIP 相對尋址限制為 32 位偏移量,與代碼段的最大偏移量為 2GB。
我也知道(從斯塔克的評論中)Linux 內核從 0xffff_ffff_8000_0000 開始其代碼段(https://www.kernel.org/doc/html/latest/x86/x86_64/mm.html):
ffffffff80000000 | -2 GB | ffffffff9fffffff | 512 MB | kernel text mapping, mapped to physical address 0
如果 Linux 內核的代碼段與其大部分資料段的距離超過 2GB,那么除了使用 RIP 相對尋址之外,它如何訪問它?
我認為 -mcmodel=kernel 代碼模型可以將 32 位絕對地址符號擴展為 64 位,這允許可執行檔案在不使用 -mcmodel=large 的情況下訪問虛擬地址空間的高 2GB。這無濟于事,因為在該區域中找不到內核的資料段。同時, -mcmodel=large 使可執行檔案使用 64 位絕對地址訪問資料段,這會減慢內核速度并使其變得更大。
Linux內核如何訪問資料段,是否使用大代碼模型訪問虛擬地址空間的0xffff_8000_0000_0000區域?
uj5u.com熱心網友回復:
我認為混淆是在 gcc 記憶體模型和 64 位 CPU 的 MMU 之間。使用內核記憶體模型生成的代碼使用帶符號的 32 位偏移量,這意味著內核中的所有符號必須適合地址空間的頂部 2GB。這并沒有改變內核中的虛擬地址指標是 64 位的事實,其中 48 位左右是重要的,允許通過頁表和 MMU 間接訪問內核或當前用戶空間中的任何內容。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/407169.html
標籤:
