2.2 敏感指令與特權指令的交鋒:為什麼有些架構天生適合虛擬化?#
一場指令集之間的「體檢」#
普佩克–戈德堡定理提供了體檢表:把一個指令集的所有指令拿來分類,檢查是否「敏感指令 ⊆ 特權指令」。體檢結果直接決定這個架構的虛擬化命運。
及格者:IBM 大型機家族#
System/360、370 及其後裔是為數不多的天生理科生:
- 設計之初就明確劃分問題狀態(problem state)與監督狀態(supervisor state)兩種特權等級;
- 所有會觸碰系統資源的指令(I/O、頁表、中斷控制、停機)都被定義為特權指令;
- 在問題狀態執行它們 → 一律觸發 程式中斷(program interrupt),控制權自動交回 VMM。
體檢結論:敏感指令全數落在特權集合內 → 天生可虛擬化。 這不是偶然——IBM 在設計 360 時就計畫用一套硬體服務從小型科學計算到大型商業系統的各種需求,乾淨的分層是當時的設計文化。CP-40 的成功絕非運氣。
其他及格者:VAX 與 Motorola 68k#
1977 年 DEC 推出的 VAX-11/780 更進一步:指令集設計文件中直接寫明,某些指令(如 CHMX 改變特權模式)在低權限執行時會觸發 reserved instruction fault。VAX 的設計者甚至把「支援虛擬機」列為明確設計目標。Motorola 68010 以上的 68k 家族在虛擬模式下也表現良好,Sun 等公司曾用它打造虛擬化解決方案。
這些案例印證:1970 年代的硬體設計文化是「先想好特權模型,再畫指令集」——那是一個硬體昂貴、設計謹慎、每條指令都要寫進教科書的時代。
不及格者的名單正在變長#
但浪潮正在轉向。到了 1970 年代末,市場力量開始重塑指令集的誕生方式:
1970 年代初的指令集:
由大公司架構師委員會花數年精心設計(IBM 360、DEC PDP-11)
→ 特權模型清晰
1980 年代起的指令集:
由市場壓力驅動、背負相容性包袱、快速迭代(x86)
→ 特權模型千瘡百孔
相容性成為新的暴君。 當 8086 必須能跑 8080 的程式、80286 必須能跑 8086 的程式、80386 又要兼容 286 的分段模式……每一代的「歷史包袱」都會留下幾條行為曖昧的指令。而 PC 時代的設計者從未想過「有一天會有人想在這顆 CPU 上跑 hypervisor」——PC 就是要給單一使用者、單一作業系統用的,何必講究特權模型?
關鍵交鋒:三種「敏感但不特權」的災難模式#
定理告訴我們,災難來自敏感指令「漏網」成非特權指令。x86 上的經典案例有三種形態:
- 靜默降級(Silent privilege-drop):如
POP FS、POP GS、SGDT、SIDT等,在 Ring 3 執行不報錯,但會讀取/寫入系統級狀態 → guest 得知了(甚至污染了)真實的系統狀態,幻覺穿幫。 - 條件行為(Behavior depends on privilege):某些指令的副作用隨當前特權等級而變 → VMM 無法用單一方式模擬。
- 可自檢模式(Self-probing):guest 可以偵測「我到底跑在哪種環境」→ 破壞鐵律一的等效性。
學術與產業的分岔回應#
面對不及格的指令集,理論上只有三條出路——這個三分法將主導接下來五十年的虛擬化工程史:
| 路線 | 概念 | 代價 | 代表 |
|---|---|---|---|
| 修改 guest 作業系統(Paravirtualization 半虛擬化) | 把敏感指令改成顯式的「呼叫 hypervisor」介面 | 必須改原始碼,相容性受限 | Xen(1998–2003)、IBM 的 LPAR 思想 |
| 二進制動態翻譯(DBT) | 掃描 guest 機器碼,在執行前替換敏感指令 | 工程極度複雜 | VMware(1998) |
| 改造硬體 | 在 CPU 裡加入新的特權等級,讓 VMM 成為「硬體之下的環」 | 需要 Intel/AMD 合作 | VT-x / AMD-V(2005–06) |
1974 年的定理,已經把 1998 年的 VMware、2003 年的 Xen、2005 年的 VT-x 全部預言完畢。理論跑贏了工程二十年。
歷史關聯:這場「敏感 vs 特權」的交鋒最終以硬體的勝利告終——但在此之前,x86 世界必須先經歷一場「不可能」的絕望(第 3 章)與一次天才的黑魔法(第 4 章)。