簡體   English   中英

定時器中斷 (CLNT) 和 __stack_chk_fail with RISC-V

[英]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 CSR_SCRATCH的交換寄存器tp如果為零(第一次發生)將它們設置為相等。
  • tp的描述符中讀取sp s0等...。
  • 對中斷進行操作。

但是, tp似乎與當前正在運行的(中斷的任務)相同。 因此看起來sp的更改,更具體地說,堆棧保護器在中斷中不被理解,因此它可以覆蓋中斷任務當前正在運行的 memory。事實上,我已經逐步完成並觀察到了這一點。

但是我的 kernel 似乎在 QEMU 中啟動,所以我認為問題出在我的代碼上。


作為參考,這是我的設置:我的計時器順序是:

  • 如果 timer > timer_match AND timermatch != 0 設置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
  • 設置下一個 PC = mtvec (Linux 使用一體式中斷處理程序)

在處理陷阱時,我(原子地):

  • Set mepc = mtval = pc <<注意:這似乎是正確的,規范是這樣說的,kernel 改進了 mepc。
  • 設置mtval = pc
  • 設置mstatus.mpie = mstatus.mie
  • 設置mstatus.mie = 0
  • 設置下一個 PC = mtvec

調用mret I 時(原子地):

  • 設置mstatus.mie = mstatus.mpie
  • 設置mstatus.mpie = 1
  • 設置下一個 PC = 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM