aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2011-05-31 19:23:03 -0700
committerAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2011-05-31 19:23:03 -0700
commitf1bb8270a16a5bb24e674d48dfb0b86e42a6ed92 (patch)
treeda55d8f3eade6b1e65f34d51265b7e2a8be94d55
parent2641a9b24f176ca3edf83c471276fdc8f1d0ea86 (diff)
downloadspike-f1bb8270a16a5bb24e674d48dfb0b86e42a6ed92.zip
spike-f1bb8270a16a5bb24e674d48dfb0b86e42a6ed92.tar.gz
spike-f1bb8270a16a5bb24e674d48dfb0b86e42a6ed92.tar.bz2
[sim] fault on failed addr translations
previously, a bad PTE would segfault the simulator, rather than sending the fault to the OS.
-rw-r--r--riscv/mmu.h22
1 files changed, 21 insertions, 1 deletions
diff --git a/riscv/mmu.h b/riscv/mmu.h
index 21b493e..6033e98 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -49,7 +49,10 @@ public:
#define load_func(type) \
type##_t load_##type(reg_t addr) { \
if(unlikely(addr % sizeof(type##_t))) \
+ { \
+ badvaddr = addr; \
throw trap_load_address_misaligned; \
+ } \
addr = translate(addr, false, false); \
dcsim_tick(dcsim, dtlbsim, addr, sizeof(type##_t), false); \
return *(type##_t*)(mem+addr); \
@@ -58,7 +61,10 @@ public:
#define store_func(type) \
void store_##type(reg_t addr, type##_t val) { \
if(unlikely(addr % sizeof(type##_t))) \
+ { \
+ badvaddr = addr; \
throw trap_store_address_misaligned; \
+ } \
addr = translate(addr, true, false); \
dcsim_tick(dcsim, dtlbsim, addr, sizeof(type##_t), true); \
*(type##_t*)(mem+addr) = val; \
@@ -89,7 +95,10 @@ public:
#endif
{
if(unlikely(addr % 4))
+ {
+ badvaddr = addr;
throw trap_instruction_address_misaligned;
+ }
reg_t paddr = translate(addr, false, true);
insn = *(insn_t*)(mem+paddr);
@@ -174,7 +183,10 @@ private:
{
pte = walk(addr);
if(!(pte & PTE_E))
+ {
+ badvaddr = addr;
throw trap;
+ }
tlb_data[idx] = pte;
tlb_tag[idx] = addr >> PGSHIFT;
@@ -184,7 +196,10 @@ private:
if(supervisor)
access_type <<= 3;
if(unlikely(!(access_type & pte & PTE_PERM)))
+ {
+ badvaddr = addr;
throw trap;
+ }
return (addr & (PGSIZE-1)) | ((pte >> PTE_PPN_SHIFT) << PGSHIFT);
}
@@ -218,7 +233,12 @@ private:
// if this PTE is from a larger PT, fake a leaf
// PTE so the TLB will work right
reg_t vpn = addr >> PGSHIFT;
- pte |= ptd | (vpn & ((1<<(ptshift))-1)) << PTE_PPN_SHIFT;
+ ptd |= (vpn & ((1<<(ptshift))-1)) << PTE_PPN_SHIFT;
+
+ // fault if physical addr is invalid
+ reg_t ppn = ptd >> PTE_PPN_SHIFT;
+ if((ppn << PGSHIFT) + (addr & (PGSIZE-1)) < memsz)
+ pte = ptd;
break;
}
else if(!(ptd & PTE_T))