Browse Source

triggers: checking textra (tdata3); checking ASID and VMID

pull/1160/head
YenHaoChen 3 years ago
parent
commit
8318edfb5f
  1. 48
      riscv/triggers.cc
  2. 11
      riscv/triggers.h

48
riscv/triggers.cc

@ -3,6 +3,11 @@
#include "processor.h"
#include "triggers.h"
#define ASIDMAX(SXLEN) (SXLEN == 32 ? 9 : 16)
#define SATP_ASID(SXLEN) (SXLEN == 32 ? SATP32_ASID : SATP64_ASID)
#define VMIDMAX(HSXLEN) (HSXLEN == 32 ? 7 : 14)
#define HGATP_VMID(HSXLEN) (HSXLEN == 32 ? HGATP32_VMID : HGATP64_VMID)
#define CSR_TEXTRA_MHVALUE(XLEN) (XLEN == 32 ? CSR_TEXTRA32_MHVALUE : CSR_TEXTRA64_MHVALUE)
#define CSR_TEXTRA_MHSELECT(XLEN) (XLEN == 32 ? CSR_TEXTRA32_MHSELECT : CSR_TEXTRA64_MHSELECT)
#define CSR_TEXTRA_SBYTEMASK(XLEN) (XLEN == 32 ? CSR_TEXTRA32_SBYTEMASK : CSR_TEXTRA64_SBYTEMASK)
@ -39,6 +44,21 @@ unsigned trigger_t::legalize_mhselect(bool h_enabled) const noexcept {
return convert[mhselect];
}
mhselect_mode_t trigger_t::mhselect_mode(bool h_enabled) const noexcept {
switch (legalize_mhselect(h_enabled)) {
case 0: // ignore mhvalue
return MHSELECT_MODE_IGNORE;
case 4: // match only if mcontext equal mhvalue
case 1: // match only if mcontext equal {mhvalue, 1b'0}
case 5: // match only if mcontext equal {mhvalue, 1b'1}
return MHSELECT_MODE_MCONTEXT;
case 2: // match only if hgapt.VMID equal {mhvalue, 1b'0}
case 6: // match only if hgapt.VMID equal {mhvalue, 1b'1}
return MHSELECT_MODE_VMID;
default: assert(false);
}
}
reg_t trigger_t::tdata3_read(const processor_t * const proc) const noexcept {
auto xlen = proc->get_xlen();
reg_t tdata3 = 0;
@ -59,6 +79,30 @@ void trigger_t::tdata3_write(processor_t * const proc, const reg_t val) noexcept
sselect = (sselect_t)((proc->extension_enabled_const('S') && get_field(val, CSR_TEXTRA_SSELECT(xlen)) == SSELECT_ASID) ? SSELECT_ASID : SSELECT_IGNORE);
}
bool trigger_t::textra_match(processor_t * const proc) const noexcept
{
auto xlen = proc->get_xlen();
auto hsxlen = proc->get_xlen(); // use xlen since no hsxlen
state_t * const state = proc->get_state();
assert(sselect <= SSELECT_MAXVAL);
if (sselect == SSELECT_ASID) {
const reg_t satp = state->satp->read();
const reg_t asid = get_field(satp, SATP_ASID(xlen));
if (asid != (svalue & ((1 << ASIDMAX(xlen)) - 1)))
return false;
}
mhselect_mode_t mode = mhselect_mode(proc->extension_enabled('H'));
if (mode == MHSELECT_MODE_VMID) { // 2 and 6 are vmid
const reg_t vmid = get_field(state->hgatp->read(), HGATP_VMID(hsxlen));
if (vmid != (mhselect_compare(proc->extension_enabled('H')) & ((1 << VMIDMAX(hsxlen)) - 1)))
return false;
}
return true;
}
reg_t disabled_trigger_t::tdata1_read(const processor_t * const proc) const noexcept
{
auto xlen = proc->get_xlen();
@ -410,7 +454,7 @@ std::optional<match_result_t> module_t::detect_memory_access_match(operation_t o
* entire chain did not match. This is allowed by the spec, because the final
* trigger in the chain will never get `hit` set unless the entire chain
* matches. */
auto result = trigger->detect_memory_access_match(proc, operation, address, data);
auto result = trigger->textra_match(proc) ? trigger->detect_memory_access_match(proc, operation, address, data) : std::nullopt;
if (result.has_value() && !trigger->get_chain())
return result;
@ -426,7 +470,7 @@ std::optional<match_result_t> module_t::detect_trap_match(const trap_t& t) noexc
return std::nullopt;
for (auto trigger: triggers) {
auto result = trigger->detect_trap_match(proc, t);
auto result = trigger->textra_match(proc) ? trigger->detect_trap_match(proc, t) : std::nullopt;
if (result.has_value())
return result;
}

11
riscv/triggers.h

@ -36,6 +36,12 @@ typedef enum {
SSELECT_MAXVAL = 2
} sselect_t;
typedef enum {
MHSELECT_MODE_IGNORE,
MHSELECT_MODE_MCONTEXT,
MHSELECT_MODE_VMID,
} mhselect_mode_t;
struct match_result_t {
match_result_t(const timing_t t=TIMING_BEFORE, const action_t a=ACTION_DEBUG_EXCEPTION) {
timing = t;
@ -77,6 +83,7 @@ public:
virtual std::optional<match_result_t> detect_memory_access_match(processor_t UNUSED * const proc,
operation_t UNUSED operation, reg_t UNUSED address, std::optional<reg_t> UNUSED data) noexcept { return std::nullopt; }
virtual std::optional<match_result_t> detect_trap_match(processor_t UNUSED * const proc, const trap_t UNUSED & t) noexcept { return std::nullopt; }
bool textra_match(processor_t * const proc) const noexcept;
protected:
action_t legalize_action(reg_t val) const noexcept;
@ -84,6 +91,10 @@ protected:
private:
unsigned legalize_mhselect(bool h_enabled) const noexcept;
mhselect_mode_t mhselect_mode(bool h_enabled) const noexcept;
unsigned mhselect_compare(bool h_enabled) const noexcept {
return legalize_mhselect(h_enabled) == 4 ? mhvalue : (mhvalue << 1) + (mhselect >> 2); // mhvalue or {mhvalue, mhselect[2]}
}
sselect_t sselect;
unsigned svalue;
unsigned sbytemask;

Loading…
Cancel
Save