Added code to avoid most interrupt/trap cycles. PiperOrigin-RevId: 716757966 Change-Id: I4ef6b8ee0fe03a230ebe76fa065ba6073322733c
diff --git a/cheriot/cheriot_state.cc b/cheriot/cheriot_state.cc index cbbdc22..6caa2c0 100644 --- a/cheriot/cheriot_state.cc +++ b/cheriot/cheriot_state.cc
@@ -49,6 +49,7 @@ namespace cheriot { using EC = ::mpact::sim::riscv::ExceptionCode; +using PB = ::mpact::sim::cheriot::CheriotRegister::PermissionBits; using ::mpact::sim::generic::operator*; // NOLINT: used below (clang error). using ::mpact::sim::riscv::IsaExtension; using ::mpact::sim::riscv::RiscVCounterCsr; @@ -683,6 +684,38 @@ interrupt_info_list_.push_back(info); counter_interrupts_taken_.Increment(1); + // Check that executing the interrupt handler will not cause an interrupt. If + // it will, we need to halt instead. Also, verify that we are not trapping + // from the first instruction of the trap handler itself. + if ((epc == trap_target) || !pcc_->tag() || + !pcc_->HasPermission(PB::kPermitExecute) || + !pcc_->IsInBounds(trap_target, 4)) { + if (epc == trap_target) { + std::string trap_list; + int i = 0; + for (auto &info : interrupt_info_list_) { + absl::StrAppend(&trap_list, " [", i++, + "]: ", info.is_interrupt ? "Interrupt" : "Trap", + " was taken", " at 0x", + absl::Hex(info.epc, absl::kZeroPad8), " cause: 0x", + absl::Hex(info.cause), " tval: 0x", + absl::Hex(info.tval, absl::kZeroPad8), "\n"); + } + LOG(FATAL) << absl::StrCat("Recursive trap at 0x", absl::Hex(epc), "\n", + trap_list, "\n"); + } else { + LOG(FATAL) << absl::StrCat( + info.is_interrupt ? "Interrupt" : "Trap", " handler execution at 0x", + absl::Hex(trap_target), + " will cause an interrupt due to mtcc " + "value/tag/permissions/bounds violation!\n" + "mtcc: ", + pcc()->AsString(), "\n", " ", + info.is_interrupt ? "Interrupt" : "Trap", " was taken at 0x", + absl::Hex(epc), " cause: 0x", absl::Hex(info.cause), " tval: 0x", + absl::Hex(info.tval), "\n"); + } + } } // Called upon returning from an interrupt or exception.
diff --git a/cheriot/cheriot_top.cc b/cheriot/cheriot_top.cc index f74fc76..798ccfe 100644 --- a/cheriot/cheriot_top.cc +++ b/cheriot/cheriot_top.cc
@@ -210,16 +210,8 @@ bool CheriotTop::ExecuteInstruction(Instruction *inst) { // Check that pcc has tag set. if (!pcc_->tag()) { - if (state_->mtcc()->tag()) { - state_->HandleCheriRegException(inst, inst->address(), - EC::kCapExTagViolation, pcc_); - return true; - } - // If the mtcc tag is not set, then we would get an infinite loop of - // exceptions. Better to exit. - LOG(ERROR) << absl::StrCat("Infinite exception loop detected at ", - absl::Hex(inst->address()), " - halting"); - RequestHalt(HaltReason::kSimulatorError, inst); + state_->HandleCheriRegException(inst, inst->address(), + EC::kCapExTagViolation, pcc_); return true; } // Check that pcc has execute permission.