[英]Timer Interrupts (CLNT) and __stack_chk_fail with RISC-V
我正在編寫一個模擬器,我花了很長時間來弄清楚 CPU 應該做什么。 我有一個幾乎一直有效的系統。 我可以運行 NOMMU RV32 Linux kernel 如果我非常小心地選擇我的 CLNT:CPU 計時器比率以獲得真正的幸運。
我正在盡我所能模仿這個 Stack Overflow 答案所說的內容: RISC-V 中斷處理流程
而且,老實說,它似乎運作良好。 我可以運行用戶空間程序並讓我的計時器以 250 Hz 運行,除了有時 kernel 崩潰,更具體地說,它幾乎總是在__stack_chk_fail
上。 挖掘之后,我仍然不知道內核對中斷的處理是如何不到處崩潰的。 因為,它看起來像是在中斷時,會發生以下情況:
CSR_SCRATCH
的交換寄存器tp
如果為零(第一次發生)將它們設置為相等。tp
的描述符中讀取sp
s0
等...。 但是, tp
似乎與當前正在運行的(中斷的任務)相同。 因此看起來sp
的更改,更具體地說,堆棧保護器在中斷中不被理解,因此它可以覆蓋中斷任務當前正在運行的 memory。事實上,我已經逐步完成並觀察到了這一點。
但是我的 kernel 似乎在 QEMU 中啟動,所以我認為問題出在我的代碼上。
作為參考,這是我的設置:我的計時器順序是:
mip.mtip
否則清除。mie.mtie == 1
AND mip.mtip == 1
AND mstatus.mie == 1
則觸發中斷。觸發定時器中斷時(原子地):
mstatus.mpie = mstatus.mie
mstatus.mie = 0
mepc = pc
mtval = 0
mtcause = 0x80000007
mtvec
(Linux 使用一體式中斷處理程序)在處理陷阱時,我(原子地):
mepc = mtval = pc
<<注意:這似乎是正確的,規范是這樣說的,kernel 改進了 mepc。mtval = pc
mstatus.mpie = mstatus.mie
mstatus.mie = 0
mtvec
調用mret
I 時(原子地):
mstatus.mie = mstatus.mpie
mstatus.mpie = 1
mepc
任何想法發生了什么?
這可能不是 100% 正確,但這似乎能夠使系統穩定。
從 pi-maker 的 rvc,事實證明 kernel 正常運行至關重要,您必須設置mstatus.mpp
位,否則它將覆蓋 memory。
正確的解決方案似乎在這里: https://github.com/PiMaker/rvc/blob/master/src/trap.h#L48
但是,為了測試,我能夠通過以下方式讓我的項目工作。 除了上述的操作...
如果定時器中斷:
privilege
存儲到mstatus.mpp
privilege
設置為3
。 如果像ebreak
這樣的陷阱:
privilege
存儲到mstatus.mpp
privilege
設置為3
。 如果mret
:
privilege
存儲到mstatus.mpp
privilege
設置為舊mstatus.mpp
我不將privilege
位用於任何其他用途。 (請注意,這可能是不正確的,因為所選的 CSR 應根據權限級別而變化,但這似乎有效,¯\ (ツ) /¯
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.