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.