Adds information about exceptions/interrupts to interactive prompt. Adds capability to break on interrupt and/or exceptions and their returns. PiperOrigin-RevId: 663036503 Change-Id: Ie3b89c2375808528280c24a8a81f4307945183da
diff --git a/cheriot/BUILD b/cheriot/BUILD index 8380337..15fce63 100644 --- a/cheriot/BUILD +++ b/cheriot/BUILD
@@ -543,6 +543,7 @@ "@com_google_absl//absl/container:btree", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/functional:any_invocable", + "@com_google_absl//absl/log", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", @@ -550,6 +551,7 @@ "@com_google_mpact-riscv//riscv:stoull_wrapper", "@com_google_mpact-sim//mpact/sim/generic:core", "@com_google_mpact-sim//mpact/sim/generic:core_debug_interface", + "@com_google_mpact-sim//mpact/sim/generic:counters", "@com_google_mpact-sim//mpact/sim/generic:debug_command_shell_interface", "@com_google_mpact-sim//mpact/sim/generic:instruction", "@com_google_mpact-sim//mpact/sim/generic:type_helpers",
diff --git a/cheriot/cheriot_state.cc b/cheriot/cheriot_state.cc index 28edaec..e0c194d 100644 --- a/cheriot/cheriot_state.cc +++ b/cheriot/cheriot_state.cc
@@ -241,7 +241,9 @@ util::AtomicMemoryOpInterface *atomic_memory) : generic::ArchState(id), tagged_memory_(memory), - atomic_tagged_memory_(atomic_memory) { + atomic_tagged_memory_(atomic_memory), + counter_interrupts_taken_("interrupts_taken", 0), + counter_interrupt_returns_("interrupt_returns", 0) { for (auto &[name, index] : std::vector<std::pair<std::string, unsigned>>{ {"c0", 0b0'00000}, {"c1", 0b0'00001}, {"c2", 0b0'00010}, {"c3", 0b0'00011}, {"c4", 0b0'00100}, {"c5", 0b0'00101}, @@ -258,6 +260,8 @@ {"mepcc", 0b1'11111}}) { cap_index_map_.emplace(name, index); } + CHECK_OK(AddCounter(&counter_interrupts_taken_)); + CHECK_OK(AddCounter(&counter_interrupt_returns_)); // Create root capabilities and the special capability CSRs. executable_root_ = new CheriotRegister(this, "executable_root"); executable_root_->ResetExecuteRoot(); @@ -604,8 +608,8 @@ void CheriotState::Trap(bool is_interrupt, uint64_t trap_value, uint64_t exception_code, uint64_t epc, const Instruction *inst) { - // LOG(INFO) << "Trap: " << std::hex << is_interrupt << " " << trap_value << " - // " << exception_code << " " << epc; Call the handler. + // LOG(INFO) << "Trap: " << std::hex << is_interrupt << " " << trap_value + // << " " << exception_code << " " << epc; // Call the handler. if (on_trap_ != nullptr) { bool res = on_trap_(is_interrupt, trap_value, exception_code, epc, inst); // If the handler returns true, the trap has been handled. Just return. @@ -651,6 +655,7 @@ set_branch(true); // TODO(torerik): set next pc mstatus_->Submit(); + counter_interrupts_taken_.Increment(1); } // CheckForInterrupt is called whenever any relevant bits in the interrupt @@ -682,7 +687,6 @@ Trap(/*is_interrupt*/ true, 0, *available_interrupt_code_, epc, nullptr); // Clear pending interrupt. is_interrupt_available_ = false; - ++interrupt_handler_depth_; available_interrupt_code_ = InterruptCode::kNone; }
diff --git a/cheriot/cheriot_state.h b/cheriot/cheriot_state.h index c736f71..b24f5e3 100644 --- a/cheriot/cheriot_state.h +++ b/cheriot/cheriot_state.h
@@ -30,6 +30,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "mpact/sim/generic/arch_state.h" +#include "mpact/sim/generic/counters.h" #include "mpact/sim/generic/data_buffer.h" #include "mpact/sim/generic/instruction.h" #include "mpact/sim/generic/operand_interface.h" @@ -60,6 +61,7 @@ using ::mpact::sim::generic::DataBuffer; using ::mpact::sim::generic::Instruction; using ::mpact::sim::generic::ReferenceCount; +using ::mpact::sim::generic::SimpleCounter; using ::mpact::sim::riscv::InterruptCode; using ::mpact::sim::riscv::IsaExtension; using ::mpact::sim::riscv::PrivilegeMode; @@ -288,11 +290,23 @@ // Indicates that the program has returned from handling an interrupt. This // decrements the interrupt handler depth and should be called by the // implementations of mret, sret, and uret. - void SignalReturnFromInterrupt() { --interrupt_handler_depth_; } + void SignalReturnFromInterrupt() { counter_interrupt_returns_.Increment(1); } // Returns the depth of the interrupt handler currently being executed, or // zero if no interrupt handler is being executed. - int InterruptHandlerDepth() const { return interrupt_handler_depth_; } + int InterruptHandlerDepth() const { + return counter_interrupts_taken_.GetValue() - + counter_interrupt_returns_.GetValue(); + } + // Returns the interrupt counters. This allows code to be connected to the + // counters when the value changes. + SimpleCounter<int64_t> *counter_interrupts_taken() { + return &counter_interrupts_taken_; + } + + SimpleCounter<int64_t> *counter_interrupt_returns() { + return &counter_interrupt_returns_; + } // Returns true if a capability register with the given base should be // revoked. @@ -434,7 +448,8 @@ CheriotVectorState *rv_vector_ = nullptr; // For interrupt handling. bool is_interrupt_available_ = false; - int interrupt_handler_depth_ = 0; + SimpleCounter<int64_t> counter_interrupts_taken_; + SimpleCounter<int64_t> counter_interrupt_returns_; InterruptCode available_interrupt_code_ = InterruptCode::kNone; // By default, execute in machine mode. PrivilegeMode privilege_mode_ = PrivilegeMode::kMachine;
diff --git a/cheriot/cheriot_top.cc b/cheriot/cheriot_top.cc index 47002d3..14d1cbf 100644 --- a/cheriot/cheriot_top.cc +++ b/cheriot/cheriot_top.cc
@@ -73,6 +73,7 @@ counter_pc_("pc", 0), cap_reg_re_{ R"((\w+)\.(top|base|length|tag|permissions|object_type|reserved))"} { + CHECK_OK(AddChildComponent(*state_)); Initialize(); }
diff --git a/cheriot/debug_command_shell.cc b/cheriot/debug_command_shell.cc index 43537b4..f174d56 100644 --- a/cheriot/debug_command_shell.cc +++ b/cheriot/debug_command_shell.cc
@@ -17,6 +17,7 @@ #include <cstdint> #include <cstring> #include <fstream> +#include <functional> #include <istream> #include <ostream> #include <string> @@ -24,6 +25,7 @@ #include <vector> #include "absl/functional/any_invocable.h" +#include "absl/log/log.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/numbers.h" @@ -51,6 +53,59 @@ using HaltReason = ::mpact::sim::generic::CoreDebugInterface::HaltReason; using ::mpact::sim::generic::operator*; // NOLINT: used below (clang error). +DebugCommandShell::InterruptListener::InterruptListener(CoreAccess *core_access) + : core_access_(core_access), + top_(static_cast<CheriotTop *>(core_access->debug_interface)), + taken_listener_(std::bind_front(&InterruptListener::SetTakenValue, this)), + return_listener_( + std::bind_front(&InterruptListener::SetReturnValue, this)) { + top_->state()->counter_interrupts_taken()->AddListener(&taken_listener_); + top_->state()->counter_interrupt_returns()->AddListener(&return_listener_); +} + +void DebugCommandShell::InterruptListener::SetReturnValue(int64_t value) { + if (interrupt_info_list_.empty()) { + LOG(ERROR) << "Interrupt stack is empty"; + return; + } + auto info = interrupt_info_list_.front(); + interrupt_info_list_.pop_front(); + // If breakpoints are enabled, then request a halt of the appropriate type. + if (info.is_interrupt && interrupts_enabled_) + top_->RequestHalt(kInterruptReturn, nullptr); + if (!info.is_interrupt && exceptions_enabled_) + top_->RequestHalt(kExceptionReturn, nullptr); +} + +void DebugCommandShell::InterruptListener::SetTakenValue(int64_t value) { + InterruptInfo info; + bool ok = true; + // Read the values of the interrupt registers. + auto res = core_access_->debug_interface->ReadRegister("mcause"); + ok &= res.ok(); + if (ok) info.cause = res.value(); + + res = core_access_->debug_interface->ReadRegister("mtval"); + ok &= res.ok(); + if (ok) info.tval = res.value(); + + res = core_access_->debug_interface->ReadRegister("mepcc"); + ok &= res.ok(); + if (ok) info.epc = res.value(); + + if (!ok) { + LOG(ERROR) << "Failed to read interrupt registers"; + return; + } + info.is_interrupt = (info.cause & 0x8000'0000u) != 0; + // If breakpoints are enabled, the request a halt of the appropriate type. + if (info.is_interrupt && interrupts_enabled_) + top_->RequestHalt(kInterruptTaken, nullptr); + if (!info.is_interrupt && exceptions_enabled_) + top_->RequestHalt(kExceptionTaken, nullptr); + interrupt_info_list_.push_front(info); +} + // The constructor initializes all the regular expressions and the help string. DebugCommandShell::DebugCommandShell() : quit_re_{R"(\s*quit\s*)"}, @@ -123,6 +178,9 @@ according to FORMAT. Default format is x32. break [set] VALUE - set breakpoint at address VALUE. break [set] SYMBOL - set breakpoint at value of SYMBOL. + '$exception' and '$interrupt are special + symbols to break upon entry to and return + from exception/interrupt handlers. break set #<N> - reactivate breakpoint index N. break #<N> - reactivate breakpoint index N. break clear VALUE - clear breakpoint at address VALUE. @@ -175,8 +233,15 @@ reg_vector_.push_back("mscratchc"); } +DebugCommandShell::~DebugCommandShell() { + for (auto *listener : interrupt_listeners_) { + delete listener; + } +} + void DebugCommandShell::AddCore(const CoreAccess &core_access) { core_access_.push_back(core_access); + interrupt_listeners_.push_back(new InterruptListener(&core_access_.back())); core_action_point_id_.push_back(0); core_action_point_info_.emplace_back(); } @@ -218,6 +283,19 @@ case *HaltReason::kDataWatchPoint: absl::StrAppend(&prompt, "Stopped at data watchpoint\n"); break; + case InterruptListener::kInterruptTaken: + absl::StrAppend(&prompt, "Stopped at taken interrupt\n"); + break; + case InterruptListener::kInterruptReturn: + absl::StrAppend(&prompt, + "Stopped at return from interrupt handler\n"); + break; + case InterruptListener::kExceptionTaken: + absl::StrAppend(&prompt, "Stopped at exception\n"); + break; + case InterruptListener::kExceptionReturn: + absl::StrAppend(&prompt, "Stopped at return exception handler\n"); + break; case *HaltReason::kProgramDone: absl::StrAppend(&prompt, "Program done\n"); break; @@ -252,6 +330,16 @@ } absl::StrAppend(&prompt, "\n"); } + auto &info_list = + interrupt_listeners_[current_core_]->interrupt_info_list(); + int count = 0; + for (auto iter = info_list.rbegin(); iter != info_list.rend(); ++iter) { + auto const &info = *iter; + absl::StrAppend(&prompt, "[", count++, "] ", + info.is_interrupt ? "interrupt" : "exception", " ", + info.is_interrupt ? GetInterruptDescription(info) + : GetExceptionDescription(info)); + } absl::StrAppend(&prompt, "[", current_core_, "] > "); while (!command_streams_.empty()) { auto ¤t_is = *command_streams_.back(); @@ -455,16 +543,31 @@ // break set VALUE | SYMBOL if (std::string str_value; - RE2::FullMatch(line_view, *set_break_re_, &str_value)) { + RE2::FullMatch(line_view, *set_break_re_, &str_value) || + RE2::FullMatch(line_view, *set_break2_re_, &str_value)) { if (str_value == "$branch") { auto *cheriot_interface = reinterpret_cast<CheriotDebugInterface *>( core_access_[current_core_].debug_interface); cheriot_interface->SetBreakOnControlFlowChange(true); continue; + } else if (str_value == "$exception") { + if (interrupt_listeners_[current_core_]->AreExceptionsEnabled()) { + os << "Break on exceptions are already enabled\n"; + continue; + } + interrupt_listeners_[current_core_]->SetEnableExceptions(true); + continue; + } else if (str_value == "$interrupt") { + if (interrupt_listeners_[current_core_]->AreInterruptsEnabled()) { + os << "Break on interrupts are already enabled\n"; + continue; + } + interrupt_listeners_[current_core_]->SetEnableInterrupts(true); + continue; } auto result = GetValueFromString(current_core_, str_value, /*radix=*/0); if (!result.ok()) { - os << absl::StrCat("Error: '", str_value, "' ", + os << absl::StrCat("Error: ?????? '", str_value, "' ", result.status().message()) << std::endl; os.flush(); @@ -538,6 +641,8 @@ if (!status.ok()) { os << absl::StrCat("Error: ", status.message(), "\n"); } + } else { + os << absl::StrCat("No such active breakpoint: #", index, "\n"); } continue; } @@ -566,6 +671,20 @@ core_access_[current_core_].debug_interface); cheriot_interface->SetBreakOnControlFlowChange(false); continue; + } else if (str_value == "$exception") { + if (!interrupt_listeners_[current_core_]->AreExceptionsEnabled()) { + os << "Break on exceptions are already disabled\n"; + continue; + } + interrupt_listeners_[current_core_]->SetEnableExceptions(false); + continue; + } else if (str_value == "$interrupt") { + if (!interrupt_listeners_[current_core_]->AreInterruptsEnabled()) { + os << "Break on interrupts are already disabled\n"; + continue; + } + interrupt_listeners_[current_core_]->SetEnableInterrupts(false); + continue; } auto result = GetValueFromString(current_core_, str_value, /*radix=*/0); if (!result.ok()) { @@ -632,40 +751,6 @@ continue; } - // break SYMBOL | VALUE - if (std::string str_value; - RE2::FullMatch(line_view, *set_break2_re_, &str_value)) { - if (str_value == "$branch") { - auto *cheriot_interface = reinterpret_cast<CheriotDebugInterface *>( - core_access_[current_core_].debug_interface); - cheriot_interface->SetBreakOnControlFlowChange(true); - continue; - } - auto result = GetValueFromString(current_core_, str_value, /*radix=*/0); - if (!result.ok()) { - os << absl::StrCat("Error: '", str_value, "' ", - result.status().message()) - << std::endl; - os.flush(); - continue; - } - auto cmd_result = - core_access_[current_core_].debug_interface->SetSwBreakpoint( - result.value()); - if (!cmd_result.ok()) { - os << "Error: " << cmd_result.message() << std::endl; - os.flush(); - continue; - } - core_access_[current_core_] - .breakpoint_map[core_access_[current_core_].breakpoint_index++] = - result.value(); - os << absl::StrCat("Breakpoint set at 0x", - absl::Hex(result.value(), absl::PadSpec::kZeroPad8)) - << std::endl; - continue; - } - // watch set SYMBOL | VALUE <length> [r|w|rw] if (std::string str_value, length_value, rw_value; RE2::FullMatch( line_view, *set_watch_re_, &str_value, &length_value, &rw_value)) { @@ -1457,11 +1542,9 @@ // inserted and return. uint64_t bp_address = pcc + inst->size(); inst->DecRef(); - bool bp_set = false; // See if there is a bp on that address already, if so, don't try to set // another one. if (!core_access_[current_core_].debug_interface->HasBreakpoint(bp_address)) { - bp_set = true; auto bp_set_res = core_access_[current_core_].debug_interface->SetSwBreakpoint( bp_address); @@ -1684,6 +1767,159 @@ return absl::OkStatus(); } +std::string DebugCommandShell::GetInterruptDescription( + const InterruptInfo &info) { + std::string output; + if (!info.is_interrupt) return output; + switch (info.cause & 0x7fff'ffff) { + case 0: + absl::StrAppend(&output, "User software interrupt"); + break; + case 1: + absl::StrAppend(&output, "Supervisor software interrupt"); + break; + case 3: + absl::StrAppend(&output, "Machine software interrupt"); + break; + case 4: + absl::StrAppend(&output, "User timer interrupt"); + break; + case 5: + absl::StrAppend(&output, "Supervisor timer interrupt"); + break; + case 7: + absl::StrAppend(&output, "Machine timer interrupt"); + break; + case 8: + absl::StrAppend(&output, "User external interrupt"); + break; + case 9: + absl::StrAppend(&output, "Supervisor external interrupt"); + break; + case 11: + absl::StrAppend(&output, "Machine external interrupt"); + break; + default: + absl::StrAppend(&output, "Error - Unknown interrupt"); + break; + } + absl::StrAppend(&output, "\n"); + return output; +} + +std::string DebugCommandShell::GetExceptionDescription( + const InterruptInfo &info) { + std::string output; + if (info.is_interrupt) return output; + absl::StrAppend(&output, " Exception taken at ", absl::Hex(info.epc), ": "); + switch (info.cause) { + case 0: + absl::StrAppend(&output, "Instruction address misaligned: "); + absl::StrAppend(&output, ": ", absl::Hex(info.tval)); + break; + case 1: + absl::StrAppend(&output, "Instruction access fault"); + break; + case 2: + absl::StrAppend(&output, "Illegal instruction"); + absl::StrAppend(&output, " opcode: ", absl::Hex(info.tval)); + break; + case 3: + absl::StrAppend(&output, "Breakpoint instruction"); + break; + case 4: + absl::StrAppend(&output, "Load address misaligned"); + absl::StrAppend(&output, ": ", absl::Hex(info.tval)); + break; + case 5: + absl::StrAppend(&output, "Load access fault"); + break; + case 6: + absl::StrAppend(&output, "Store/AMO address misaligned"); + absl::StrAppend(&output, ": ", absl::Hex(info.tval)); + break; + case 7: + absl::StrAppend(&output, "Store/AMO access fault"); + break; + case 8: + absl::StrAppend(&output, "Environment call from U-mode"); + break; + case 9: + absl::StrAppend(&output, "Environment call from S-mode"); + break; + case 11: + absl::StrAppend(&output, "Environment call from M-mode"); + break; + case 12: + absl::StrAppend(&output, "Instruction page fault"); + absl::StrAppend(&output, ": ", absl::Hex(info.tval)); + break; + case 13: + absl::StrAppend(&output, "Load page fault"); + absl::StrAppend(&output, ": ", absl::Hex(info.tval)); + break; + case 15: + absl::StrAppend(&output, "Store/AMO page fault"); + absl::StrAppend(&output, ": ", absl::Hex(info.tval)); + break; + case 0x1c: { + absl::StrAppend(&output, "CHERI exception"); + switch (info.tval & 0x1f) { + case 0: + absl::StrAppend(&output, ": none??"); + break; + case 1: + absl::StrAppend(&output, ": bounds violation"); + break; + case 2: + absl::StrAppend(&output, ": tag violation"); + break; + case 3: + absl::StrAppend(&output, ": seal violation"); + break; + case 0x11: + absl::StrAppend(&output, ": PERMIT_EXECUTION violation"); + break; + case 0x12: + absl::StrAppend(&output, ": PERMIT_LOAD violation"); + break; + case 0x13: + absl::StrAppend(&output, ": PERMIT_STORE violation"); + break; + case 0x15: + absl::StrAppend(&output, ": PERMIT_STORE_CAPABILITY violation"); + break; + case 0x18: + absl::StrAppend(&output, + ": PERMIT_ACCESS_SYSTEM_REGISTERS violation"); + break; + default: + absl::StrAppend(&output, ": unknown cause"); + break; + } + int cap_indx = (info.tval >> 5) & 0x1f; + if (cap_indx < 16) + absl::StrAppend(&output, " c", cap_indx); + else if (cap_indx == 28) + absl::StrAppend(&output, " mtcc"); + else if (cap_indx == 29) + absl::StrAppend(&output, " mtdc"); + else if (cap_indx == 30) + absl::StrAppend(&output, " mscratchc"); + else if (cap_indx == 31) + absl::StrAppend(&output, " mepcc"); + else + absl::StrAppend(&output, " unknown capability"); + break; + } + default: + absl::StrAppend(&output, "Error - Unknown trap"); + break; + } + absl::StrAppend(&output, "\n"); + return output; +} + } // namespace cheriot } // namespace sim } // namespace mpact
diff --git a/cheriot/debug_command_shell.h b/cheriot/debug_command_shell.h index 0a3b218..71fc7b0 100644 --- a/cheriot/debug_command_shell.h +++ b/cheriot/debug_command_shell.h
@@ -19,11 +19,11 @@ #include <cstdint> #include <deque> -#include <fstream> #include <iostream> #include <istream> #include <ostream> #include <string> +#include <utility> #include <vector> #include "absl/container/btree_map.h" @@ -32,7 +32,11 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" +#include "cheriot/cheriot_top.h" +#include "mpact/sim/generic/core_debug_interface.h" +#include "mpact/sim/generic/counters_base.h" #include "mpact/sim/generic/debug_command_shell_interface.h" +#include "mpact/sim/generic/type_helpers.h" #include "re2/re2.h" namespace mpact::sim::generic { @@ -43,14 +47,17 @@ namespace sim { namespace cheriot { +using ::mpact::sim::generic::CounterValueSetInterface; using ::mpact::sim::generic::DebugCommandShellInterface; +using HaltReason = ::mpact::sim::generic::CoreDebugInterface::HaltReason; +using ::mpact::sim::generic::operator*; // NOLINT: used below (clang error). // This class implements an interactive command shell for a set of cores // simulated by the MPact simulator using the CoreDebugInterface. class DebugCommandShell : public DebugCommandShellInterface { public: - // Default constructor is deleted. DebugCommandShell(); + ~DebugCommandShell() override; // Add core access to the system. All cores must be added before calling Run. void AddCore(const CoreAccess &core_access) override; @@ -81,6 +88,67 @@ bool is_enabled; }; + // Struct to track interrupt/trap information. + struct InterruptInfo { + bool is_interrupt; + uint32_t cause; + uint32_t tval; + uint32_t epc; + }; + + // The interrupt listener class is used to track interrupts/exceptions and + // returns from interrupts/exceptions, so that breakpoints can be set on these + // events. + class InterruptListener { + public: + // Convenience class to provide listeners to the counters. + class Listener : public CounterValueSetInterface<int64_t> { + public: + explicit Listener(absl::AnyInvocable<void(int64_t)> callback) + : callback_(std::move(callback)) {} + + private: + void SetValue(const int64_t &value) override { callback_(value); } + absl::AnyInvocable<void(int64_t)> callback_; + }; + + using InterruptInfoList = std::deque<InterruptInfo>; + static constexpr uint32_t kInterruptTaken = + *HaltReason::kUserSpecifiedMin + 1; + static constexpr uint32_t kInterruptReturn = + *HaltReason::kUserSpecifiedMin + 2; + static constexpr uint32_t kExceptionTaken = + *HaltReason::kUserSpecifiedMin + 3; + static constexpr uint32_t kExceptionReturn = + *HaltReason::kUserSpecifiedMin + 4; + + explicit InterruptListener(CoreAccess *core_access); + void SetEnableExceptions(bool value) { exceptions_enabled_ = value; } + void SetEnableInterrupts(bool value) { interrupts_enabled_ = value; } + bool AreExceptionsEnabled() const { return exceptions_enabled_; } + bool AreInterruptsEnabled() const { return interrupts_enabled_; } + + const InterruptInfoList &interrupt_info_list() const { + return interrupt_info_list_; + } + + private: + void SetReturnValue(int64_t value); + void SetTakenValue(int64_t value); + + CoreAccess *core_access_; + CheriotTop *top_; + bool interrupts_enabled_ = false; + bool exceptions_enabled_ = false; + InterruptInfoList interrupt_info_list_; + Listener taken_listener_; + Listener return_listener_; + }; + + // Helper method to get the interrupt description. + std::string GetInterruptDescription(const InterruptInfo &info); + std::string GetExceptionDescription(const InterruptInfo &info); + // Helper method for formatting single data buffer value. std::string FormatSingleDbValue(generic::DataBuffer *db, const std::string &format, int width, @@ -194,6 +262,7 @@ std::deque<std::string> previous_commands_; std::vector<absl::btree_map<int, ActionPointInfo>> core_action_point_info_; std::vector<int> core_action_point_id_; + std::vector<InterruptListener *> interrupt_listeners_; }; } // namespace cheriot
diff --git a/cheriot/riscv_cheriot_priv_instructions.cc b/cheriot/riscv_cheriot_priv_instructions.cc index e729c5d..ee2b29b 100644 --- a/cheriot/riscv_cheriot_priv_instructions.cc +++ b/cheriot/riscv_cheriot_priv_instructions.cc
@@ -36,8 +36,8 @@ // Set mstatus:mpie to 1. mstatus->set_mpie(1); mstatus->set_mpp(*PrivilegeMode::kMachine); - state->SignalReturnFromInterrupt(); mstatus->Submit(); + state->SignalReturnFromInterrupt(); } void RiscVPrivWfi(const Instruction *inst) {