From dffd42169bafb625cd30f8c0a9181dbebb85fe56 Mon Sep 17 00:00:00 2001 From: Ming-Yi Lai Date: Thu, 4 Jan 2024 11:52:13 +0800 Subject: Zicfilp: Check that the next insn is a lpad if ELP is LP_EXPECTED --- riscv/execute.cc | 2 ++ riscv/processor.cc | 15 +++++++++++++++ riscv/processor.h | 2 ++ 3 files changed, 19 insertions(+) diff --git a/riscv/execute.cc b/riscv/execute.cc index 4f5860b..b2532c9 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -280,6 +280,7 @@ void processor_t::step(size_t n) in_wfi = false; insn_fetch_t fetch = mmu->load_insn(pc); + execute_insn_prehook(fetch.insn); if (debug && !state.serialized) disasm(fetch.insn); pc = execute_insn_logged(this, pc, fetch); @@ -291,6 +292,7 @@ void processor_t::step(size_t n) // Main simulation loop, fast path. for (auto ic_entry = _mmu->access_icache(pc); ; ) { auto fetch = ic_entry->data; + execute_insn_prehook(fetch.insn); pc = execute_insn_fast(this, pc, fetch); ic_entry = ic_entry->next; if (unlikely(ic_entry->tag != pc)) diff --git a/riscv/processor.cc b/riscv/processor.cc index c2b2d45..48e5f16 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -94,6 +94,14 @@ processor_t::~processor_t() delete disassembler; } +static void zicfilp_check_if_lpad_required(const elp_t elp, insn_t insn) +{ + if (unlikely(elp == elp_t::LP_EXPECTED)) { + // also see riscv/lpad.h for more checks performed + software_check((insn.bits() & MASK_LPAD) == MATCH_LPAD, LANDING_PAD_FAULT); + } +} + static void bad_option_string(const char *option, const char *value, const char *msg) { @@ -966,6 +974,13 @@ const char* processor_t::get_symbol(uint64_t addr) return sim->get_symbol(addr); } +void processor_t::execute_insn_prehook(insn_t insn) +{ + if (extension_enabled(EXT_ZICFILP)) { + zicfilp_check_if_lpad_required(state.elp, insn); + } +} + void processor_t::disasm(insn_t insn) { uint64_t bits = insn.bits(); diff --git a/riscv/processor.h b/riscv/processor.h index 4285773..22ad04a 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -312,6 +312,8 @@ public: void clear_waiting_for_interrupt() { in_wfi = false; }; bool is_waiting_for_interrupt() { return in_wfi; }; + void execute_insn_prehook(insn_t insn); + private: const isa_parser_t * const isa; const cfg_t * const cfg; -- cgit v1.1