Zircon 核心不變情形

在 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 註冊器。

    我們希望避免在核心程式碼中意外使用 floatdouble 類型,但無論如何,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 仍會為使用 floatdouble 的程式碼產生 x87 指令 (並使用 x87 註冊器)。

    • 堆疊上未於 %rsp 儲存資料。 請注意,使用者土地程式碼可以執行以下動作:SysV x86-64 ABI 可讓函式將資料儲存在「紅區」,也就是 %rsp 下方的 128 個位元組。 不過,核心程式碼無法使用紅色區域,因為中斷時間可能會幹擾此區域,CPU 會在叫用中斷處理常式時,立即將資料推送到 %rsp 的下方。

    這通常會透過將 -mno-red-zone 傳遞給編譯器的方式強制執行。