fix trap handling if illegal fetch (PMP) and U-mode CSRs
This commit is contained in:
@ -296,6 +296,10 @@ inline bool is_count_limit_enabled(finish_cond_e cond){
|
||||
return (cond & finish_cond_e::COUNT_LIMIT) == finish_cond_e::COUNT_LIMIT;
|
||||
}
|
||||
|
||||
inline bool is_jump_to_self_enabled(finish_cond_e cond){
|
||||
return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF;
|
||||
}
|
||||
|
||||
template <typename ARCH>
|
||||
typename vm_impl<ARCH>::compile_func vm_impl<ARCH>::decode_inst(code_word_t instr){
|
||||
for(auto& e: qlut[instr&0x3]){
|
||||
@ -307,7 +311,6 @@ typename vm_impl<ARCH>::compile_func vm_impl<ARCH>::decode_inst(code_word_t inst
|
||||
template <typename ARCH>
|
||||
typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){
|
||||
// we fetch at max 4 byte, alignment is 2
|
||||
enum {TRAP_ID=1<<16};
|
||||
code_word_t insn = 0;
|
||||
auto *const data = (uint8_t *)&insn;
|
||||
auto pc=start;
|
||||
@ -315,14 +318,14 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
!(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){
|
||||
auto res = fetch_ins(pc, data);
|
||||
if(res!=iss::Ok){
|
||||
auto new_pc = super::core.enter_trap(TRAP_ID, pc.val, 0);
|
||||
res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data);
|
||||
if(res!=iss::Ok) throw simulation_stopped(0);
|
||||
this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max());
|
||||
pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::max(), pc.val, 0);
|
||||
} else {
|
||||
if (is_jump_to_self_enabled(cond) &&
|
||||
(insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||
auto f = decode_inst(insn);
|
||||
pc = (this->*f)(pc, insn);
|
||||
}
|
||||
if ((cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF &&
|
||||
(insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||
auto f = decode_inst(insn);
|
||||
pc = (this->*f)(pc, insn);
|
||||
}
|
||||
return pc;
|
||||
}
|
||||
|
Reference in New Issue
Block a user