問題1:內核如何處理來自用戶空間的陷阱?
進入內核空間的路徑:先uservec
,後usertrap
;
返回用戶空間的路徑:先usertrapret
,後userret
;
問題2:函數uservec
都做了哪些事?
- 保存除了
pc
之外的所有寄存器的值; - 切換內核頁表;
- 切換內核棧;
- 調用
usertrap
;
問題3:函數usertrap
都做了哪些事?
- 判斷陷阱的原因;
- 處理陷阱;
- 從內核中返回,即調用
usertrapret
;
問題4:函數usertrapret
都做了哪些事?
爲下一次來自用戶空間的陷阱做好準備,包括:
- 修改
stvec
指向uservec
; - 準備好
trapframe
字段; - 設置
sepc
爲之前保存的用戶pc
; - 調用
userret
;
問題5:函數userret
都做了哪些事?
- 切換用戶頁表;
- 恢復用戶寄存器的值;
- 在
sscratch
中保存用戶trapframe
的地址; - 使用
sret
指令返回到用戶空間;
問題6:進程的trapframe
有哪些性質?
- 什麼時候創建?
創建進程時,分配一個頁用於進程的trapframe
,並映射到用戶的虛擬地址TRAPFRAME
。 - 相關的指針有哪些?
p->trapframe
;
問題7:在處理來自用戶空間的陷阱時,是如何使用trapframe
的?
- 進入內核空間時,在
trapframe
上保存屬於用戶空間的寄存器的值; - 返回用戶空間時,保存
trapframe
爲下次陷阱做好準備;
比如,當前進程的內核棧指針、usertrap
的地址、內核頁表的地址等;
問題8:uservec
函數和trampoline
頁的聯繫?
-
uservec
函數在trampline
頁上。 - 基於事實:
trampoline
頁被映射到內核頁表和用戶頁表的虛擬地址是相同的,所以在修改satp
後,uservec
可繼續執行。
問題9:陷阱幀trapframe
上有哪些數據?
- 當前進程內核棧的指針;
- 當前CPU的hartid;
-
usertrap
的地址; - 內核頁表的地址;
問題10:在處理來自用戶空間的陷阱過程中,a0
和sscratch
進行了幾次交換?
兩次,分別是
- 在進入內核的過程中,
uservec
在一開始就使用csrrw
指令交換a0
和sscratch
交換後,原用戶空間的a0
值被保存到sscratch
中,即sscratch
此時的值是陷阱發生時用戶空間的a0
,a0
的值是內核先前在sscratch
中放入的值。 - 在返回用戶空間的過程中,userret交換
a0
和sscratch
交換前,sscratch
中記錄的是陷阱發生時保存的用戶空間的a0
值,交換後,a0
的值就是先前保存的用戶空間的值;
交換前,在usertrapret
調用userret
時,給a0
傳遞了指向TRAPFRAME
的指針,交換後,sscratch
中記錄的就是指向TRAPFRAME
的指針;