這個版本程式碼大上不少, 難度也增加不少, 為減少一點複雜度, 這篇省略了 int 0x13 isr 的 stack 部份。這次要把 proc_a, proc_b 的 stack 保存/恢復。
為了要達成在真實模式下無法達到的 stack 保存/恢復 (其實是我想不到什麼方法, 所以只好出動保護模式), 需要使用保護模式的權限切換, 所以程式才變成如此複雜, 若不使用權限切換, 則和真實模式一樣, iret/int 不會
保存/恢復 stack。
在這樣的環境下, iret/int 指令除了之前提到的行為還會將 %ss:%esp 的值也一起
保存/恢復。
一開始, 在權限方面的 gdt, idt 設定有些問題 (要在 ring0/ring3 切換), bochs 幫了很大的忙, 讓我除錯的速度加快不少, 若沒這個 bochs, 我可能還在冥想程式哪裡出錯了。真的很佩服之前寫 os 的人, 頭腦掉很清楚才能寫出正確的 os 程式。
我沒打算解釋保護模式下的權限切換, 從 L209 開始看起即可。這邊的 code 就很單純, 把 stack_frame_a, stack_fram_b 填上需要的值, 和之前的真實模式比起來, 多了 %ss:%esp。而在保護模式下, %ss, %cs 也變成了 selector, 所以如果不熟保護模式, 也不要管這個, 單純看 %eip, % esp 即可, 重點是把 process switch 搞懂, 而不是注重在別的地方。
如果你真想完全搞懂, 需要保護模式相關知識:
- 如何進入保護模式?
- 如何設定 idt?
- 如何從 ring0 -> ring3 -> ring0?
請參考:
杨文博的自己動手寫作業系統
先來檢視這些事情:
- stack frame a, stack frame b 的內容
- tss
- 執行 iret 切換到 proc_a 檢查 %ss:%esp
- int $0x13 檢查 %ss:%esp
手工圖又來了, 老問題, 很醜是吧!別為難我了, 看到那複雜的曲線, 我可畫不了精美的版本, 就將就點。 stack_fame_a, stack_frame_b 多了兩個欄位用來保存 %ss, %esp, iret 發動前, 將 %ss:%esp 指到
① 或
② , iret 發動後, eip, es, flag, esp, ss 就會依序被填入
stack_fame_a + 4
stack_fame_a + 8
stack_fame_a +12
stack_fame_a +16
stack_fame_a + 20
所指到的值。
而 int $0x30 發動時, stack 會怎麼變化呢?
這時是從 ring 3 -> ring0, stack 會使用 tss 的 ss0:esp0 來填入 %ss:%esp。
所以 tss 的 ss0:esp0 該怎麼設定呢?
填入
③ 或
④ 的位址。
假設現在要切換到 proc_a, 程式要做的事情有:
tss 的 esp0 要填入
③ 的位址 (ss 簡單起見, 使用相同的 selector), %esp 填入
① 的位址, 最後發動 iret。
從 proc_a 執行 int $0x13 時, stack 變化方式為:
esp 的值變成
③ 而
ss, esp, flag, es, eip 依序 push 到 stack,當最終切換到 int 0x13 isr 時, eps 在
① 的位置, 在 push %eax 之後, 剛好把 proc_a 所有的東西 (%eax, ss, esp, flag, es, eip) 都保存下來。
這時 int 0x13 isr 繼續準備 proc_b 的切換動作:
tss 的 esp0 要填入
④ 的位址 (ss 簡單起見, 使用相同的 selector), %esp 填入
② 的位址, 最後發動 iret。
疑, 沒有我想像中的難表達, 不過不知道讀者們有沒搞懂, 希望沒讓你們更糊塗了。
最後還剩下 isr 本身的 stack, 這部份相對簡單, 應該可以不用出 x86 process switch implementation (4) 了。
source code:
https://github.com/descent/process protected branch
① ② ③ ④ symbol ref:
http://blog.yam.com/picryam/article/10903476
http://blog.aican.info/2008/04/blog-post_10.html
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。