iT邦幫忙

2025 iThome 鐵人賽

DAY 29
0
自我挑戰組

30 天 hypervisor 入門系列 第 29

Day 29 今日檢討

  • 分享至 

  • xImage
  •  

檢討

這段時間期時也沒啥好寫的,每天做的事情就是查 BIOS 服務 -> 實作 -> 測試 -> 爆掉 -> 再找哪裡實現錯誤。我在想目前最大的問題是對組語不夠熟練並且我沒有做測試。
當我在實作 BIOS 服務時,經常踩到相同的坑,舉例來說:

  • push/pop 不平衡 (經常用了 push 保存暫存器後就忘記 pop 了)
  • stack 沒有平衡,臨時調整 sp 開闢 stack 空間暫存數據然後沒有恢復
  • 忘記 push 資料導致從 BIOS 中斷服務程式返回後行為出現一堆問題

目前觀測也很被動:能看的訊息多半在 BIOS/Host 兩側留下,且必須經由 Host 才能刷新。

比如當我忘記 pop 時會發生兩個問題,暫存器沒有被正確恢復,ret 會跳到錯誤地址然後觸發 int 6h 的 UND 非法指令,但當錯誤發生到處發 int 6h 已經距離很遠了。或者有時候 BIOS 的返回信息沒給正確,導致 bootloader 在計算扇區調用 int 13h 去讀資料時意外的發生 int 0h 的除以零的錯誤。經常看著程式碼一天過去也沒多少進度,寫一段停一段,實在找不出問題沒想法就拿去問 ai 請他給我一些想法。坦白說,目前有不少 assembly 是經過 AI 重構,光靠我硬寫真的很多地方真得慘不忍睹。

總結

總結下來最大的問題還是 1. 對 bios 的理解止於表面,實作功能時得回去看功能描述並且還經常做錯 2. 慘不忍睹的組語能力 3. 沒有實作測試模組驗證行為的正確性。

差異測試

舉例來說若想保證行為正確,可以考慮差異測試。
qemu 是經過驗證非常可靠的模擬環境,以它作為基準我們無需去猜測 hv 是否有哪裡實現錯誤可能的原因是甚麼。比如我們可以同步 qemu 與 hv 並實作差異測試:

QEMU 執行 1 條指令 -> HV 也執行 1 條 → 比對兩邊狀態(暫存器) -> 第一個不一致處就是錯誤的發生點。

這樣就無須像現在一樣用通靈的方式去猜問題是甚麼。

不過這需要仰賴一條指令 INT 3h(1 byte),這是 x86 系統專門用於條是錯誤保留的指令入口,長度為 1 byte 可在任何位置插入命令而不影響周圍指令。我們甚至可以實作一個簡單的調適器,在需要的地方插入 0xCC (INT 3h),執行到目標指令時就:

  • 在 Guest 的 INT 3 handler 保存現場 (通用暫存器、FLAGS、CR0/3/4 ....)
  • 並在 INT 3 handler 主動觸發 VM-exit 切回 Host 讓 Host 讀取快照
  • 透過管道將 Host 的快照輸出,同時驅動 qemu 單步執行後輸出快照,並比對差異

這樣就不需通過通靈去猜問題發生在哪裡。

簡易調適器(INT 3h)

而對於那些非 hv 的錯誤比如 bootloader 或是 bios 的錯誤可透過延伸 int 3h 在 Host 內建簡易調適器解決。比如我們有註冊到 kvm 的 memory slot 與 struct struct kvm_regs 等,可以以此為基礎實作斷點、單步調適、暫存器、記憶體觀察與修改、差異輸出。


上一篇
Day 28 實現 BIOS INT 服務
下一篇
Day 30 結語
系列文
30 天 hypervisor 入門30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言