@@ -25,6 +25,17 @@ void emu_update_uart_interrupts(riscv_t *rv)
2525 plic_update_interrupts (attr -> plic );
2626}
2727
28+ /*
29+ * Linux kernel might create signal frame when returning from trap
30+ * handling, which modifies the SEPC CSR. Thus, the fault instruction
31+ * cannot always redo. For example, invalid memory access causes SIGSEGV.
32+ */
33+ extern bool need_handle_signal ;
34+ #define CHECK_PENDING_SIGNAL (rv , signal_flag ) \
35+ do { \
36+ signal_flag = (rv->csr_sepc != rv->last_csr_sepc); \
37+ } while (0)
38+
2839#define MMIO_R 1
2940#define MMIO_W 0
3041
@@ -297,8 +308,14 @@ static uint32_t mmu_read_w(riscv_t *rv, const uint32_t addr)
297308 uint32_t level ;
298309 pte_t * pte = mmu_walk (rv , addr , & level );
299310 bool ok = MMU_FAULT_CHECK (read , rv , pte , addr , PTE_R );
300- if (unlikely (!ok ))
311+ if (unlikely (!ok )) {
312+ #if RV32_HAS (SYSTEM ) && !RV32_HAS (ELF_LOADER )
313+ CHECK_PENDING_SIGNAL (rv , need_handle_signal );
314+ if (need_handle_signal )
315+ return 0 ;
316+ #endif
301317 pte = mmu_walk (rv , addr , & level );
318+ }
302319
303320 {
304321 get_ppn_and_offset ();
@@ -323,8 +340,14 @@ static uint16_t mmu_read_s(riscv_t *rv, const uint32_t addr)
323340 uint32_t level ;
324341 pte_t * pte = mmu_walk (rv , addr , & level );
325342 bool ok = MMU_FAULT_CHECK (read , rv , pte , addr , PTE_R );
326- if (unlikely (!ok ))
343+ if (unlikely (!ok )) {
344+ #if RV32_HAS (SYSTEM ) && !RV32_HAS (ELF_LOADER )
345+ CHECK_PENDING_SIGNAL (rv , need_handle_signal );
346+ if (need_handle_signal )
347+ return 0 ;
348+ #endif
327349 pte = mmu_walk (rv , addr , & level );
350+ }
328351
329352 get_ppn_and_offset ();
330353 return memory_read_s (ppn | offset );
@@ -338,8 +361,14 @@ static uint8_t mmu_read_b(riscv_t *rv, const uint32_t addr)
338361 uint32_t level ;
339362 pte_t * pte = mmu_walk (rv , addr , & level );
340363 bool ok = MMU_FAULT_CHECK (read , rv , pte , addr , PTE_R );
341- if (unlikely (!ok ))
364+ if (unlikely (!ok )) {
365+ #if RV32_HAS (SYSTEM ) && !RV32_HAS (ELF_LOADER )
366+ CHECK_PENDING_SIGNAL (rv , need_handle_signal );
367+ if (need_handle_signal )
368+ return 0 ;
369+ #endif
342370 pte = mmu_walk (rv , addr , & level );
371+ }
343372
344373 {
345374 get_ppn_and_offset ();
@@ -364,8 +393,14 @@ static void mmu_write_w(riscv_t *rv, const uint32_t addr, const uint32_t val)
364393 uint32_t level ;
365394 pte_t * pte = mmu_walk (rv , addr , & level );
366395 bool ok = MMU_FAULT_CHECK (write , rv , pte , addr , PTE_W );
367- if (unlikely (!ok ))
396+ if (unlikely (!ok )) {
397+ #if RV32_HAS (SYSTEM ) && !RV32_HAS (ELF_LOADER )
398+ CHECK_PENDING_SIGNAL (rv , need_handle_signal );
399+ if (need_handle_signal )
400+ return ;
401+ #endif
368402 pte = mmu_walk (rv , addr , & level );
403+ }
369404
370405 {
371406 get_ppn_and_offset ();
@@ -390,8 +425,14 @@ static void mmu_write_s(riscv_t *rv, const uint32_t addr, const uint16_t val)
390425 uint32_t level ;
391426 pte_t * pte = mmu_walk (rv , addr , & level );
392427 bool ok = MMU_FAULT_CHECK (write , rv , pte , addr , PTE_W );
393- if (unlikely (!ok ))
428+ if (unlikely (!ok )) {
429+ #if RV32_HAS (SYSTEM ) && !RV32_HAS (ELF_LOADER )
430+ CHECK_PENDING_SIGNAL (rv , need_handle_signal );
431+ if (need_handle_signal )
432+ return ;
433+ #endif
394434 pte = mmu_walk (rv , addr , & level );
435+ }
395436
396437 get_ppn_and_offset ();
397438 memory_write_s (ppn | offset , (uint8_t * ) & val );
@@ -405,8 +446,14 @@ static void mmu_write_b(riscv_t *rv, const uint32_t addr, const uint8_t val)
405446 uint32_t level ;
406447 pte_t * pte = mmu_walk (rv , addr , & level );
407448 bool ok = MMU_FAULT_CHECK (write , rv , pte , addr , PTE_W );
408- if (unlikely (!ok ))
449+ if (unlikely (!ok )) {
450+ #if RV32_HAS (SYSTEM ) && !RV32_HAS (ELF_LOADER )
451+ CHECK_PENDING_SIGNAL (rv , need_handle_signal );
452+ if (need_handle_signal )
453+ return ;
454+ #endif
409455 pte = mmu_walk (rv , addr , & level );
456+ }
410457
411458 {
412459 get_ppn_and_offset ();
0 commit comments