aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@wdc.com>2020-06-21 19:32:09 +0530
committerAnup Patel <anup@brainfault.org>2020-07-08 16:54:00 +0530
commitb6038de3fcd71703732995bb90bd7d411d330890 (patch)
tree567325c30d07a2328432b6015adc5b108ff7b81f
parent89d2591f1b84e7755c0f46166d9e0d6ec0fe7c03 (diff)
downloadspike-b6038de3fcd71703732995bb90bd7d411d330890.zip
spike-b6038de3fcd71703732995bb90bd7d411d330890.tar.gz
spike-b6038de3fcd71703732995bb90bd7d411d330890.tar.bz2
Extend trap classes to pass more information
With hypervisor extension, we have more CSRs providing trap related information. We extend existing trap classes to pass additional trap information required by hypervisor extension. Signed-off-by: Anup Patel <anup.patel@wdc.com>
-rw-r--r--riscv/execute.cc2
-rw-r--r--riscv/insns/c_ebreak.h2
-rw-r--r--riscv/insns/ebreak.h2
-rw-r--r--riscv/mmu.cc18
-rw-r--r--riscv/mmu.h20
-rw-r--r--riscv/processor.h2
-rw-r--r--riscv/trap.h42
7 files changed, 60 insertions, 28 deletions
diff --git a/riscv/execute.cc b/riscv/execute.cc
index 4ed2753..a6c7f10 100644
--- a/riscv/execute.cc
+++ b/riscv/execute.cc
@@ -347,7 +347,7 @@ void processor_t::step(size_t n)
enter_debug_mode(DCSR_CAUSE_HWBP);
break;
case ACTION_DEBUG_EXCEPTION: {
- mem_trap_t trap(CAUSE_BREAKPOINT, t.address);
+ insn_trap_t trap(CAUSE_BREAKPOINT, t.address);
take_trap(trap, pc);
break;
}
diff --git a/riscv/insns/c_ebreak.h b/riscv/insns/c_ebreak.h
index a17200f..1c36b24 100644
--- a/riscv/insns/c_ebreak.h
+++ b/riscv/insns/c_ebreak.h
@@ -1,2 +1,2 @@
require_extension('C');
-throw trap_breakpoint();
+throw trap_breakpoint(0);
diff --git a/riscv/insns/ebreak.h b/riscv/insns/ebreak.h
index c22776c..f123f95 100644
--- a/riscv/insns/ebreak.h
+++ b/riscv/insns/ebreak.h
@@ -1 +1 @@
-throw trap_breakpoint();
+throw trap_breakpoint(0);
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index b038f23..78abd39 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -37,9 +37,9 @@ void mmu_t::flush_tlb()
static void throw_access_exception(reg_t addr, access_type type)
{
switch (type) {
- case FETCH: throw trap_instruction_access_fault(addr);
- case LOAD: throw trap_load_access_fault(addr);
- case STORE: throw trap_store_access_fault(addr);
+ case FETCH: throw trap_instruction_access_fault(addr, 0, 0);
+ case LOAD: throw trap_load_access_fault(addr, 0, 0);
+ case STORE: throw trap_store_access_fault(addr, 0, 0);
default: abort();
}
}
@@ -69,7 +69,7 @@ tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr)
return refill_tlb(vaddr, paddr, host_addr, FETCH);
} else {
if (!mmio_load(paddr, sizeof fetch_temp, (uint8_t*)&fetch_temp))
- throw trap_instruction_access_fault(vaddr);
+ throw trap_instruction_access_fault(vaddr, 0, 0);
tlb_entry_t entry = {(char*)&fetch_temp - vaddr, paddr - vaddr};
return entry;
}
@@ -137,7 +137,7 @@ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes)
else
refill_tlb(addr, paddr, host_addr, LOAD);
} else if (!mmio_load(paddr, len, bytes)) {
- throw trap_load_access_fault(addr);
+ throw trap_load_access_fault(addr, 0, 0);
}
if (!matched_trigger) {
@@ -166,7 +166,7 @@ void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes)
else
refill_tlb(addr, paddr, host_addr, STORE);
} else if (!mmio_store(paddr, len, bytes)) {
- throw trap_store_access_fault(addr);
+ throw trap_store_access_fault(addr, 0, 0);
}
}
@@ -350,9 +350,9 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode)
}
switch (type) {
- case FETCH: throw trap_instruction_page_fault(addr);
- case LOAD: throw trap_load_page_fault(addr);
- case STORE: throw trap_store_page_fault(addr);
+ case FETCH: throw trap_instruction_page_fault(addr, 0, 0);
+ case LOAD: throw trap_load_page_fault(addr, 0, 0);
+ case STORE: throw trap_store_page_fault(addr, 0, 0);
default: abort();
}
}
diff --git a/riscv/mmu.h b/riscv/mmu.h
index f89d139..edf38ed 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -66,7 +66,7 @@ public:
res += (reg_t)load_uint8(addr + i) << (i * 8);
return res;
#else
- throw trap_load_address_misaligned(addr);
+ throw trap_load_address_misaligned(addr, 0, 0);
#endif
}
@@ -76,7 +76,7 @@ public:
for (size_t i = 0; i < size; i++)
store_uint8(addr + i, data >> (i * 8));
#else
- throw trap_store_address_misaligned(addr);
+ throw trap_store_address_misaligned(addr, 0, 0);
#endif
}
@@ -165,17 +165,17 @@ public:
template<typename op> \
type##_t amo_##type(reg_t addr, op f) { \
if (addr & (sizeof(type##_t)-1)) \
- throw trap_store_address_misaligned(addr); \
+ throw trap_store_address_misaligned(addr, 0, 0); \
try { \
auto lhs = load_##type(addr); \
store_##type(addr, f(lhs)); \
return lhs; \
} catch (trap_load_page_fault& t) { \
/* AMO faults should be reported as store faults */ \
- throw trap_store_page_fault(t.get_tval()); \
+ throw trap_store_page_fault(t.get_tval(), t.get_tval2(), t.get_tinst()); \
} catch (trap_load_access_fault& t) { \
/* AMO faults should be reported as store faults */ \
- throw trap_store_access_fault(t.get_tval()); \
+ throw trap_store_access_fault(t.get_tval(), t.get_tval2(), t.get_tinst()); \
} \
}
@@ -183,7 +183,7 @@ public:
{
#ifndef RISCV_ENABLE_MISALIGNED
if (unlikely(addr & (sizeof(float128_t)-1)))
- throw trap_store_address_misaligned(addr);
+ throw trap_store_address_misaligned(addr, 0, 0);
#endif
store_uint64(addr, val.v[0]);
store_uint64(addr + 8, val.v[1]);
@@ -193,7 +193,7 @@ public:
{
#ifndef RISCV_ENABLE_MISALIGNED
if (unlikely(addr & (sizeof(float128_t)-1)))
- throw trap_load_address_misaligned(addr);
+ throw trap_load_address_misaligned(addr, 0, 0);
#endif
return (float128_t){load_uint64(addr), load_uint64(addr + 8)};
}
@@ -219,19 +219,19 @@ public:
if (auto host_addr = sim->addr_to_mem(paddr))
load_reservation_address = refill_tlb(vaddr, paddr, host_addr, LOAD).target_offset + vaddr;
else
- throw trap_load_access_fault(vaddr); // disallow LR to I/O space
+ throw trap_load_access_fault(vaddr, 0, 0); // disallow LR to I/O space
}
inline bool check_load_reservation(reg_t vaddr, size_t size)
{
if (vaddr & (size-1))
- throw trap_store_address_misaligned(vaddr);
+ throw trap_store_address_misaligned(vaddr, 0, 0);
reg_t paddr = translate(vaddr, 1, STORE);
if (auto host_addr = sim->addr_to_mem(paddr))
return load_reservation_address == refill_tlb(vaddr, paddr, host_addr, STORE).target_offset + vaddr;
else
- throw trap_store_access_fault(vaddr); // disallow SC to I/O space
+ throw trap_store_access_fault(vaddr, 0, 0); // disallow SC to I/O space
}
static const reg_t ICACHE_ENTRIES = 1024;
diff --git a/riscv/processor.h b/riscv/processor.h
index 68e13d8..a679eaa 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -284,7 +284,7 @@ public:
}
void check_pc_alignment(reg_t pc) {
if (unlikely(pc & ~pc_alignment_mask()))
- throw trap_instruction_address_misaligned(pc);
+ throw trap_instruction_address_misaligned(pc, 0, 0);
}
reg_t legalize_privilege(reg_t);
void set_privilege(reg_t);
diff --git a/riscv/trap.h b/riscv/trap.h
index ac048eb..824af6f 100644
--- a/riscv/trap.h
+++ b/riscv/trap.h
@@ -13,18 +13,23 @@ class trap_t
public:
trap_t(reg_t which) : which(which) {}
virtual const char* name();
+ virtual bool has_gva() { return false; }
virtual bool has_tval() { return false; }
virtual reg_t get_tval() { return 0; }
+ virtual bool has_tval2() { return false; }
+ virtual reg_t get_tval2() { return 0; }
+ virtual bool has_tinst() { return false; }
+ virtual reg_t get_tinst() { return 0; }
reg_t cause() { return which; }
private:
char _name[16];
reg_t which;
};
-class mem_trap_t : public trap_t
+class insn_trap_t : public trap_t
{
public:
- mem_trap_t(reg_t which, reg_t tval)
+ insn_trap_t(reg_t which, reg_t tval)
: trap_t(which), tval(tval) {}
bool has_tval() override { return true; }
reg_t get_tval() override { return tval; }
@@ -32,22 +37,45 @@ class mem_trap_t : public trap_t
reg_t tval;
};
+class mem_trap_t : public trap_t
+{
+ public:
+ mem_trap_t(reg_t which, bool gva, reg_t tval, reg_t tval2, reg_t tinst)
+ : trap_t(which), gva(gva), tval(tval), tval2(tval2), tinst(tinst) {}
+ bool has_gva() override { return gva; }
+ bool has_tval() override { return true; }
+ reg_t get_tval() override { return tval; }
+ bool has_tval2() override { return true; }
+ reg_t get_tval2() override { return tval2; }
+ bool has_tinst() override { return true; }
+ reg_t get_tinst() override { return tinst; }
+ private:
+ bool gva;
+ reg_t tval, tval2, tinst;
+};
+
#define DECLARE_TRAP(n, x) class trap_##x : public trap_t { \
public: \
trap_##x() : trap_t(n) {} \
const char* name() { return "trap_"#x; } \
};
+#define DECLARE_INST_TRAP(n, x) class trap_##x : public insn_trap_t { \
+ public: \
+ trap_##x(reg_t tval) : insn_trap_t(n, tval) {} \
+ const char* name() { return "trap_"#x; } \
+};
+
#define DECLARE_MEM_TRAP(n, x) class trap_##x : public mem_trap_t { \
public: \
- trap_##x(reg_t tval) : mem_trap_t(n, tval) {} \
+ trap_##x(reg_t tval, reg_t tval2, reg_t tinst) : mem_trap_t(n, true, tval, tval2, tinst) {} \
const char* name() { return "trap_"#x; } \
};
DECLARE_MEM_TRAP(CAUSE_MISALIGNED_FETCH, instruction_address_misaligned)
DECLARE_MEM_TRAP(CAUSE_FETCH_ACCESS, instruction_access_fault)
-DECLARE_MEM_TRAP(CAUSE_ILLEGAL_INSTRUCTION, illegal_instruction)
-DECLARE_TRAP(CAUSE_BREAKPOINT, breakpoint)
+DECLARE_INST_TRAP(CAUSE_ILLEGAL_INSTRUCTION, illegal_instruction)
+DECLARE_INST_TRAP(CAUSE_BREAKPOINT, breakpoint)
DECLARE_MEM_TRAP(CAUSE_MISALIGNED_LOAD, load_address_misaligned)
DECLARE_MEM_TRAP(CAUSE_MISALIGNED_STORE, store_address_misaligned)
DECLARE_MEM_TRAP(CAUSE_LOAD_ACCESS, load_access_fault)
@@ -59,5 +87,9 @@ DECLARE_TRAP(CAUSE_MACHINE_ECALL, machine_ecall)
DECLARE_MEM_TRAP(CAUSE_FETCH_PAGE_FAULT, instruction_page_fault)
DECLARE_MEM_TRAP(CAUSE_LOAD_PAGE_FAULT, load_page_fault)
DECLARE_MEM_TRAP(CAUSE_STORE_PAGE_FAULT, store_page_fault)
+DECLARE_MEM_TRAP(CAUSE_FETCH_GUEST_PAGE_FAULT, instruction_guest_page_fault)
+DECLARE_MEM_TRAP(CAUSE_LOAD_GUEST_PAGE_FAULT, load_guest_page_fault)
+DECLARE_INST_TRAP(CAUSE_VIRTUAL_INSTRUCTION, virtual_instruction)
+DECLARE_MEM_TRAP(CAUSE_STORE_GUEST_PAGE_FAULT, store_guest_page_fault)
#endif