Browse Source

[sim,pk] cleanups & initial virtual memory support

cs250
Andrew Waterman 15 years ago
parent
commit
6e85b4332f
  1. 1
      riscv/insns/fence_i.h
  2. 6
      riscv/insns/mfpcr.h
  3. 4
      riscv/insns/mtpcr.h
  4. 12
      riscv/mmu.cc
  5. 52
      riscv/mmu.h
  6. 1
      riscv/processor.cc
  7. 1
      riscv/riscv.mk.in

1
riscv/insns/fence_i.h

@ -0,0 +1 @@
mmu.flush_icache();

6
riscv/insns/mfpcr.h

@ -27,7 +27,11 @@ switch(insn.rtype.rs2)
break;
case 8:
val = MEMSIZE >> 12;
val = MEMSIZE >> PGSHIFT;
break;
case 9:
val = mmu.get_ptbr();
break;
case 17:

4
riscv/insns/mtpcr.h

@ -19,6 +19,10 @@ switch(insn.rtype.rs2)
compare = RS1;
break;
case 9:
mmu.set_ptbr(RS1);
break;
case 16:
tohost = RS1;
sim->set_tohost(RS1);

12
riscv/mmu.cc

@ -0,0 +1,12 @@
#include "mmu.h"
void mmu_t::flush_tlb()
{
memset(tlb_data, 0, sizeof(tlb_data)); // TLB entry itself has valid bit
flush_icache();
}
void mmu_t::flush_icache()
{
memset(icache_tag, 0, sizeof(icache_tag)); // I$ tag contains valid bit
}

52
riscv/mmu.h

@ -36,11 +36,6 @@ public:
{
}
void set_icsim(icsim_t* _icsim) { icsim = _icsim; }
void set_dcsim(icsim_t* _dcsim) { dcsim = _dcsim; }
void set_itlbsim(icsim_t* _itlbsim) { itlbsim = _itlbsim; }
void set_dtlbsim(icsim_t* _dtlbsim) { dtlbsim = _dtlbsim; }
#ifdef RISCV_ENABLE_ICSIM
# define dcsim_tick(dcsim, dtlbsim, addr, size, st) \
do { if(dcsim) (dcsim)->tick(addr, size, st); \
@ -69,9 +64,13 @@ public:
{
insn_t insn;
#ifdef RISCV_ENABLE_RVC
check_align(addr, rvc ? 2 : 4, false, true);
reg_t idx = (addr/sizeof(insn_t)) % ICACHE_ENTRIES;
if(addr % 4 == 0 && icache_tag[idx] == (addr | 1))
return icache_data[idx];
#ifdef RISCV_ENABLE_RVC
if(addr % 4 == 2 && rvc)
{
reg_t paddr_lo = translate(addr, false, true);
insn.bits = *(uint16_t*)(mem+paddr_lo);
@ -80,11 +79,17 @@ public:
reg_t paddr_hi = translate(addr+2, false, true);
insn.bits |= (uint32_t)*(uint16_t*)(mem+paddr_hi) << 16;
}
#else
}
else
#endif
{
check_align(addr, 4, false, true);
reg_t paddr = translate(addr, false, true);
insn = *(insn_t*)(mem+paddr);
#endif
icache_tag[idx] = addr | 1;
icache_data[idx] = insn;
}
#ifdef RISCV_ENABLE_ICSIM
if(icsim)
@ -112,9 +117,19 @@ public:
store_func(uint64)
reg_t get_badvaddr() { return badvaddr; }
reg_t get_ptbr() { return ptbr; }
void set_supervisor(bool sup) { supervisor = sup; }
void set_vm_enabled(bool en) { vm_enabled = en; }
void set_ptbr(reg_t addr) { ptbr = addr & ~(PGSIZE-1); }
void set_ptbr(reg_t addr) { ptbr = addr & ~(PGSIZE-1); flush_tlb(); }
void set_icsim(icsim_t* _icsim) { icsim = _icsim; }
void set_dcsim(icsim_t* _dcsim) { dcsim = _dcsim; }
void set_itlbsim(icsim_t* _itlbsim) { itlbsim = _itlbsim; }
void set_dtlbsim(icsim_t* _dtlbsim) { dtlbsim = _dtlbsim; }
void flush_tlb();
void flush_icache();
private:
char* mem;
@ -129,6 +144,10 @@ private:
pte_t tlb_data[TLB_ENTRIES];
reg_t tlb_tag[TLB_ENTRIES];
static const reg_t ICACHE_ENTRIES = 32;
insn_t icache_data[ICACHE_ENTRIES];
reg_t icache_tag[ICACHE_ENTRIES];
icsim_t* icsim;
icsim_t* dcsim;
icsim_t* itlbsim;
@ -172,7 +191,7 @@ private:
!store && !fetch && !(supervisor ? pte.sr : pte.ur))
throw trap;
return (addr % PGSIZE) | (pte.ppn << PGSHIFT);
return (addr & (PGSIZE-1)) | (pte.ppn << PGSHIFT);
}
pte_t walk(reg_t addr)
@ -219,16 +238,5 @@ private:
return pte;
}
void check_bounds(reg_t addr, int size, bool store, bool fetch)
{
if(addr >= memsz || addr + size > memsz)
{
badvaddr = addr;
if(fetch)
throw trap_instruction_access_fault;
throw store ? trap_store_access_fault : trap_load_access_fault;
}
}
friend class processor_t;
};

1
riscv/processor.cc

@ -123,6 +123,7 @@ void processor_t::set_sr(uint32_t val)
mmu.set_vm_enabled(sr & SR_VM);
mmu.set_supervisor(sr & SR_S);
mmu.flush_tlb();
xprlen = ((sr & SR_S) ? (sr & SR_SX) : (sr & SR_UX)) ? 64 : 32;
}

1
riscv/riscv.mk.in

@ -19,6 +19,7 @@ riscv_srcs = \
sim.cc \
trap.cc \
icsim.cc \
mmu.cc \
riscv_test_srcs =

Loading…
Cancel
Save