在 x86 上,Zircon 必須保留在環 0 (核心模式) 中執行的程式碼的不變性。
我們在這裡記錄了這些不變量,因為它們不一定容易測試,而 Zircon 的測試套件不一定能捕捉到不變量。
檢舉標記:
- 方向旗標 (DF) 應為 0。 這是 x86 呼叫慣例的必要條件。
如果這個標記設為 1,使用 x86 字串指示 (例如:
memcpy()
中的rep movs
或由編譯器內嵌) 可能會發生錯誤,且方向錯誤。 只要函式在傳回或呼叫其他函式之前,將其標示為 0 即可,暫時將這個標記設為 1。- 對齊檢查標記 (AC) 通常應為 0。 在支援 SMAP 的 CPU 上,可避免核心不小心讀取或寫入使用者土地資料。
每當在核心模式下執行,且啟用乾擾時,
gs_base
註冊器必須指向目前 CPU 的x86_percpu
結構。gs_base
只應變更為指向其他物件,但已停用中斷功能。 例如,只有在停用服務中斷時,才應使用swapgs
指令。編譯器會強制執行下列部分:
- 不得使用擴充暫存器 (SSE、AVX、x87 等),因為這會破壞使用者註冊狀態。
方法是將
-mno-sse
傳遞給編譯器。 這個選項是為了防止編譯器在最佳化 (例如記憶體副本) 中使用 SSE 註冊器。我們希望避免在核心程式碼中意外使用
float
或double
類型,但無論如何,GCC 和 Clang 都不會這樣。-mno-sse
不會阻止將float
/double
與任一編譯器搭配使用;編譯器會改用 x87 指令。我們利用
-msoft-float
編譯了程式碼,這導致 GCC 無法產生 x87 指示 (因此使用 x87 註冊器):GCC 6.3.0 會在float
/double
計算上出現錯誤但能回傳這些類型做為引數不過,將-msoft-float
傳遞到 Clang 似乎沒有任何作用:Clang 7.0.0 仍會為使用float
或double
的程式碼產生 x87 指令 (並使用 x87 註冊器)。- 堆疊上未於
%rsp
儲存資料。 請注意,使用者土地程式碼可以執行以下動作:SysV x86-64 ABI 可讓函式將資料儲存在「紅區」,也就是 %rsp 下方的 128 個位元組。 不過,核心程式碼無法使用紅色區域,因為中斷時間可能會幹擾此區域,CPU 會在叫用中斷處理常式時,立即將資料推送到 %rsp 的下方。
這通常會透過將
-mno-red-zone
傳遞給編譯器的方式強制執行。