1010#include <stdlib.h>
1111#include <string.h>
1212
13+ #if RV32_HAS (SYSTEM )
14+ #include "plic.h"
15+ #endif /* RV32_HAS(SYSTEM) */
16+
1317#ifdef __EMSCRIPTEN__
1418#include <emscripten.h>
1519#endif
@@ -41,6 +45,12 @@ extern struct target_ops gdbstub_ops;
4145#define IF_rs2 (i , r ) (i->rs2 == rv_reg_##r)
4246#define IF_imm (i , v ) (i->imm == v)
4347
48+ #if RV32_HAS (SYSTEM )
49+ static uint32_t reloc_enable_mmu_jalr_addr ;
50+ static bool reloc_enable_mmu = false;
51+ bool need_retranslate = false;
52+ #endif
53+
4454static void rv_trap_default_handler (riscv_t * rv )
4555{
4656 rv -> csr_mepc += rv -> compressed ? 2 : 4 ;
@@ -81,6 +91,13 @@ static inline void update_time(riscv_t *rv)
8191 rv -> csr_time [1 ] = t >> 32 ;
8292}
8393
94+ #if RV32_HAS (SYSTEM )
95+ static inline void get_time_now (struct timeval * tv )
96+ {
97+ rv_gettimeofday (tv );
98+ }
99+ #endif
100+
84101#if RV32_HAS (Zicsr )
85102/* get a pointer to a CSR */
86103static uint32_t * csr_get_ptr (riscv_t * rv , uint32_t csr )
@@ -177,6 +194,13 @@ static uint32_t csr_csrrw(riscv_t *rv, uint32_t csr, uint32_t val)
177194
178195 * c = val ;
179196
197+ /*
198+ * guestOS's process might have same VA,
199+ * so block_map cannot be reused
200+ */
201+ if (c == & rv -> csr_satp )
202+ block_map_clear (rv );
203+
180204 return out ;
181205}
182206
@@ -349,6 +373,11 @@ static set_t pc_set;
349373static bool has_loops = false;
350374#endif
351375
376+ #if RV32_HAS (SYSTEM )
377+ extern void emu_update_uart_interrupts (riscv_t * rv );
378+ static uint32_t peripheral_update_ctr = 64 ;
379+ #endif
380+
352381/* Interpreter-based execution path */
353382#define RVOP (inst , code , asm ) \
354383 static bool do_##inst(riscv_t *rv, rv_insn_t *ir, uint64_t cycle, \
@@ -539,6 +568,8 @@ FORCE_INLINE bool insn_is_unconditional_branch(uint8_t opcode)
539568
540569static void block_translate (riscv_t * rv , block_t * block )
541570{
571+ retranslate :
572+ memset (block , 0 , sizeof (block_t ));
542573 block -> pc_start = block -> pc_end = rv -> PC ;
543574
544575 rv_insn_t * prev_ir = NULL ;
@@ -551,7 +582,16 @@ static void block_translate(riscv_t *rv, block_t *block)
551582 prev_ir -> next = ir ;
552583
553584 /* fetch the next instruction */
554- const uint32_t insn = rv -> io .mem_ifetch (rv , block -> pc_end );
585+ uint32_t insn = rv -> io .mem_ifetch (rv , block -> pc_end );
586+
587+ #if RV32_HAS (SYSTEM )
588+ if (!insn && need_retranslate ) {
589+ need_retranslate = false;
590+ goto retranslate ;
591+ }
592+ #endif
593+
594+ assert (insn );
555595
556596 /* decode the instruction */
557597 if (!rv_decode (ir , insn )) {
@@ -560,8 +600,7 @@ static void block_translate(riscv_t *rv, block_t *block)
560600 break ;
561601 }
562602 ir -> impl = dispatch_table [ir -> opcode ];
563- ir -> pc = block -> pc_end ;
564- /* compute the end of pc */
603+ ir -> pc = block -> pc_end ; /* compute the end of pc */
565604 block -> pc_end += is_compressed (insn ) ? 2 : 4 ;
566605 block -> n_insn ++ ;
567606 prev_ir = ir ;
@@ -878,6 +917,14 @@ static bool runtime_profiler(riscv_t *rv, block_t *block)
878917}
879918#endif
880919
920+ #if RV32_HAS (SYSTEM )
921+ static bool rv_has_plic_trap (riscv_t * rv )
922+ {
923+ return ((rv -> csr_sstatus & SSTATUS_SIE || !rv -> priv_mode ) &&
924+ (rv -> csr_sip & rv -> csr_sie ));
925+ }
926+ #endif
927+
881928void rv_step (void * arg )
882929{
883930 assert (arg );
@@ -891,6 +938,48 @@ void rv_step(void *arg)
891938
892939 /* loop until hitting the cycle target */
893940 while (rv -> csr_cycle < cycles_target && !rv -> halt ) {
941+ #if RV32_HAS (SYSTEM )
942+ /* check for any interrupt after every block emulation */
943+
944+ /* now time */
945+ struct timeval tv ;
946+
947+ if (peripheral_update_ctr -- == 0 ) {
948+ peripheral_update_ctr = 64 ;
949+
950+ u8250_check_ready (PRIV (rv )-> uart );
951+ if (PRIV (rv )-> uart -> in_ready )
952+ emu_update_uart_interrupts (rv );
953+ }
954+
955+ get_time_now (& tv );
956+ uint64_t t = (uint64_t ) (tv .tv_sec * 1e6 ) + (uint32_t ) tv .tv_usec ;
957+
958+ if (t > attr -> timer ) {
959+ rv -> csr_sip |= RV_INT_STI ;
960+ } else {
961+ rv -> csr_sip &= ~RV_INT_STI ;
962+ }
963+
964+ if (rv_has_plic_trap (rv )) {
965+ uint32_t intr_applicable = rv -> csr_sip & rv -> csr_sie ;
966+ uint8_t intr_idx = ilog2 (intr_applicable );
967+ switch (intr_idx ) {
968+ case 1 :
969+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , SUPERVISOR_SW_INTR , 0 );
970+ break ;
971+ case 5 :
972+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , SUPERVISOR_TIMER_INTR , 0 );
973+ break ;
974+ case 9 :
975+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , SUPERVISOR_EXTERNAL_INTR , 0 );
976+ break ;
977+ default :
978+ break ;
979+ }
980+ }
981+ #endif /* RV32_HAS(SYSTEM) */
982+
894983 if (prev && prev -> pc_start != last_pc ) {
895984 /* update previous block */
896985#if !RV32_HAS (JIT )
@@ -1018,6 +1107,8 @@ static void __trap_handler(riscv_t *rv)
10181107 assert (insn );
10191108
10201109 rv_decode (ir , insn );
1110+ reloc_enable_mmu_jalr_addr = rv -> PC ;
1111+
10211112 ir -> impl = dispatch_table [ir -> opcode ];
10221113 rv -> compressed = is_compressed (insn );
10231114 ir -> impl (rv , ir , rv -> csr_cycle , rv -> PC );
@@ -1117,8 +1208,13 @@ void ecall_handler(riscv_t *rv)
11171208{
11181209 assert (rv );
11191210#if RV32_HAS (SYSTEM )
1120- syscall_handler (rv );
1121- rv -> PC += 4 ;
1211+ if (rv -> priv_mode == RV_PRIV_U_MODE ) {
1212+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , ECALL_U , 0 );
1213+ } else if (rv -> priv_mode ==
1214+ RV_PRIV_S_MODE ) { /* trap to SBI syscall handler */
1215+ rv -> PC += 4 ;
1216+ syscall_handler (rv );
1217+ }
11221218#else
11231219 SET_CAUSE_AND_TVAL_THEN_TRAP (rv , ECALL_M , 0 );
11241220 syscall_handler (rv );
0 commit comments