Browse Source

Changed supervisor mode

- initial PC is 0x2000
- PCRs renumbered
- clearing IPIs now requires a write to a different PCR
- IRQs are each given their own cause #
eos18-bringup
Andrew Waterman 15 years ago
parent
commit
8a5c0e51c3
  1. 5
      riscv/decode.h
  2. 25
      riscv/insns/mfpcr.h
  3. 26
      riscv/insns/mtpcr.h
  4. 23
      riscv/processor.cc
  5. 5
      riscv/processor.h
  6. 5
      riscv/sim.cc
  7. 20
      riscv/trap.h

5
riscv/decode.h

@ -48,11 +48,6 @@ const int JUMP_ALIGN_BITS = 1;
#define IPI_IRQ 5
#define TIMER_IRQ 7
#define CAUSE_EXCCODE 0x000000FF
#define CAUSE_IP 0x0000FF00
#define CAUSE_EXCCODE_SHIFT 0
#define CAUSE_IP_SHIFT 8
#define FP_RD_NE 0
#define FP_RD_0 1
#define FP_RD_DN 2

25
riscv/insns/mfpcr.h

@ -26,15 +26,6 @@ switch(insn.rtype.rs2)
val = cause;
break;
case 7:
val = 0;
cause &= ~(1 << (IPI_IRQ+CAUSE_IP_SHIFT));
break;
case 8:
val = mmu.memsz >> PGSHIFT;
break;
case 9:
val = mmu.get_ptbr();
break;
@ -42,23 +33,19 @@ switch(insn.rtype.rs2)
val = id;
break;
case 11:
val = vecbanks;
break;
case 12:
val = sim.num_cores();
val = pcr_k0;
break;
case 13:
val = pcr_k1;
break;
case 17:
val = sim.get_fromhost();
break;
case 24:
val = pcr_k0;
break;
case 25:
val = pcr_k1;
case 18:
val = vecbanks;
break;
default:

26
riscv/insns/mtpcr.h

@ -15,31 +15,33 @@ switch(insn.rtype.rs2)
count = RS1;
break;
case 5:
cause &= ~(1 << (TIMER_IRQ+CAUSE_IP_SHIFT));
interrupts_pending &= ~(1 << TIMER_IRQ);
compare = RS1;
break;
case 7:
sim.send_ipi(RS1);
mmu.set_ptbr(RS1);
break;
case 8:
sim.send_ipi(RS1);
break;
case 9:
mmu.set_ptbr(RS1);
interrupts_pending &= ~(1 << IPI_IRQ);
break;
case 11:
vecbanks = RS1 & 0xff;
vecbanks_count = __builtin_popcountll(vecbanks);
case 12:
pcr_k0 = RS1;
break;
case 13:
pcr_k1 = RS1;
break;
case 16:
sim.set_tohost(RS1);
break;
case 24:
pcr_k0 = RS1;
break;
case 25:
pcr_k1 = RS1;
case 18:
vecbanks = RS1 & 0xff;
vecbanks_count = __builtin_popcountll(vecbanks);
break;
}

23
riscv/processor.cc

@ -39,16 +39,19 @@ void processor_t::reset()
{
run = false;
// the ISA guarantees the following initial state
set_sr(SR_S | SR_SX);
pc = 0;
// the ISA guarantees on boot that the PC is 0x2000 and the the processor
// is in supervisor mode, and in 64-bit mode, if supported, with traps
// and virtual memory disabled. we accomplish this by setting EVEC to
// 0x2000 and *enabling* traps, then sending the core an IPI.
set_sr(SR_S | SR_SX | SR_ET | SR_IM);
evec = 0x2000;
// the following state is undefined upon boot-up,
// but we zero it for determinism
memset(XPR,0,sizeof(XPR));
memset(FPR,0,sizeof(FPR));
evec = 0;
pc = 0;
epc = 0;
badvaddr = 0;
cause = 0;
@ -118,11 +121,13 @@ void processor_t::setvl(int vlapp)
void processor_t::take_interrupt()
{
uint32_t interrupts = (cause & CAUSE_IP) >> CAUSE_IP_SHIFT;
uint32_t interrupts = interrupts_pending;
interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
if(interrupts && (sr & SR_ET))
throw trap_interrupt;
for(int i = 0; ; i++, interrupts >>= 1)
if(interrupts & 1)
throw (trap_t)(trap_irq0 + i);
}
void processor_t::step(size_t n, bool noisy)
@ -193,7 +198,7 @@ void processor_t::step(size_t n, bool noisy)
uint32_t old_count = count;
count += i;
if(old_count < compare && uint64_t(old_count) + i >= compare)
cause |= 1 << (TIMER_IRQ+CAUSE_IP_SHIFT);
interrupts_pending |= 1 << TIMER_IRQ;
}
void processor_t::take_trap(trap_t t, bool noisy)
@ -204,7 +209,7 @@ void processor_t::take_trap(trap_t t, bool noisy)
// switch to supervisor, set previous supervisor bit, disable traps
set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
cause = (cause & ~CAUSE_EXCCODE) | (t << CAUSE_EXCCODE_SHIFT);
cause = t;
epc = pc;
pc = evec;
badvaddr = mmu.get_badvaddr();
@ -212,7 +217,7 @@ void processor_t::take_trap(trap_t t, bool noisy)
void processor_t::deliver_ipi()
{
cause |= 1 << (IPI_IRQ+CAUSE_IP_SHIFT);
interrupts_pending |= 1 << IPI_IRQ;
run = true;
}

5
riscv/processor.h

@ -30,7 +30,6 @@ private:
reg_t XPR[NXPR];
freg_t FPR[NFPR];
reg_t pc;
uint32_t fsr;
// counters
reg_t cycle;
@ -38,12 +37,14 @@ private:
// privileged control registers
reg_t epc;
reg_t badvaddr;
reg_t cause;
reg_t evec;
reg_t pcr_k0;
reg_t pcr_k1;
uint32_t cause;
uint32_t interrupts_pending;
uint32_t id;
uint32_t sr; // only modify the status register using set_sr()
uint32_t fsr;
uint32_t count;
uint32_t compare;

5
riscv/sim.cc

@ -77,6 +77,11 @@ void sim_t::run(bool debug)
{
htif->wait_for_start();
// word 0 of memory contains the memory capacity in MB
mmu->store_uint32(0, memsz >> 20);
// word 1 of memory contains the core count
mmu->store_uint32(4, num_cores());
// start core 0
send_ipi(0);

20
riscv/trap.h

@ -7,7 +7,7 @@
DECLARE_TRAP(illegal_instruction), \
DECLARE_TRAP(privileged_instruction), \
DECLARE_TRAP(fp_disabled), \
DECLARE_TRAP(interrupt), \
DECLARE_TRAP(reserved0), \
DECLARE_TRAP(syscall), \
DECLARE_TRAP(breakpoint), \
DECLARE_TRAP(load_address_misaligned), \
@ -18,16 +18,14 @@
DECLARE_TRAP(vector_bank), \
DECLARE_TRAP(vector_illegal_instruction), \
DECLARE_TRAP(reserved1), \
DECLARE_TRAP(reserved2), \
DECLARE_TRAP(reserved3), \
DECLARE_TRAP(int0), \
DECLARE_TRAP(int1), \
DECLARE_TRAP(int2), \
DECLARE_TRAP(int3), \
DECLARE_TRAP(int4), \
DECLARE_TRAP(int5), \
DECLARE_TRAP(int6), \
DECLARE_TRAP(int7), \
DECLARE_TRAP(irq0), \
DECLARE_TRAP(irq1), \
DECLARE_TRAP(irq2), \
DECLARE_TRAP(irq3), \
DECLARE_TRAP(irq4), \
DECLARE_TRAP(irq5), \
DECLARE_TRAP(irq6), \
DECLARE_TRAP(irq7), \
#define DECLARE_TRAP(x) trap_##x
enum trap_t

Loading…
Cancel
Save