rv64/rv64_reset [ Functions ]
[ Top ] [ rv64 ] [ Functions ]
NAME
rv64_reset
SYNOPSIS
void rv64_reset(rv64_t* rv, uint64_t init_pc, uint64_t init_sp)
FUNCTION
Resets the RISC-V virtual processor to power-on conditions.
INPUTS
rv Pointer to the RISC-V state structure.
init_pc Initial program counter.
init_sp Initial stack pointer.
NOTE
Most hardware RISC-V implementations have vendor-specific values
of PC and SP when they power on. By offering these as parameters,
we can more or less simulate this behavior arbitrarily.
RESULT
SEE ALSO
rv64_step
SOURCE
{
rv->mepc = rv->pc;
rv->pc = init_pc;
rv64_xreg_at_put(rv, 2, init_sp);
rv->mode = PRIV_MACHINE;
rv->status = (rv64_status_t) {
.mdt = 1,
.sdt = 1,
.sxl = XLEN_64BITS,
.uxl = XLEN_64BITS,
.mprv = 0,
.mxr = 0,
.sum = 0,
.tvm = 0,
.tsr = 0,
.mpp = PRIV_USER,
.spp = 0,
.mpie = 1,
.spie = 1,
.mie = 0,
.sie = 0,
};
rv->mtvec = G_RV64_RESET_PC;
rv->mcause = g_reset;
rv->mtval = rv->mtval2 = 0;
rv->mideleg = 0;
rv->medeleg = 0;
rv->mie = 0;
rv->critical_error = false;
rv->trap_taken = false;
}
rv64/rv64_return_from_trap [ Functions ]
[ Top ] [ rv64 ] [ Functions ]
NAME
rv64_return_from_trap
SYNOPSIS
void rv64_return_from_trap(rv64_t* rv, rv64_priv_t inst_priv)
FUNCTION
If host-local code handles a trap, this function can be used to emulate an MRET or SRET instruction. In fact, the emulator itself uses this function to implement the MRET and SRET instructions.
NOTE Make sure the mepc or sepc registers are optionally updated though! A common mistake is to not bump the mepc/sepc registers past an ECALL instruction, thus resulting in an infinite trap loop.
INPUTS
rv Pointer to the RISC-V state structure
inst_priv To emulate MRET, set to PRIV_MACHINE; to emulate
SRET, set to PRIV_SUPERVISOR.
RESULT
The next time you invoke the RISC-V processor, it will be running in
user-mode again.
SEE ALSO
SOURCE
{
switch (rv->mode) {
default:
break;
case PRIV_SUPERVISOR:
rv->status.sdt = false;
break;
case PRIV_MACHINE:
rv->status.mdt = false;
break;
}
switch (inst_priv) {
default:
return;
case PRIV_SUPERVISOR: // SRET
rv->status.sie = rv->status.spie;
rv->status.spie = 1;
rv->mode = (rv->status.spp) ? PRIV_SUPERVISOR : PRIV_USER;
rv64_set_spp(rv, PRIV_USER);
rv->pc = rv->sepc;
return;
case PRIV_MACHINE: // MRET
rv->status.mie = rv->status.mpie;
rv->status.mpie = 1;
rv->mode = rv->status.mpp;
if (rv->status.mpp != PRIV_MACHINE) {
rv->status.mprv = 0;
}
rv64_set_mpp(rv, PRIV_USER);
rv->pc = rv->mepc;
return;
}
}
rv64/rv64_run_until_trap [ Functions ]
[ Top ] [ rv64 ] [ Functions ]
NAME
rv64_run_until_trap
SYNOPSIS
void rv64_run_until_trap(rv64_t* rv, slots_t* slots)
FUNCTION
Execute a RISC-V program for as long as is practicable. Abort only when a trap or interrupt is encountered.
INPUTS
rv Pointer to the RISC-V state structure for this virtual
processor.
slots Pointer to the slots_t containing the memory map accessible
to this virtual processor.
RESULT
BUGS
This procedure can potentially run indefinitely if no traps occur.
SEE ALSO
rv64/rv64_step
SOURCE
{
rv->trap_taken = false;
while (!rv->trap_taken && !rv->critical_error) {
rv64_step(rv, slots);
}
}
rv64/rv64_step [ Functions ]
[ Top ] [ rv64 ] [ Functions ]
NAME
rv64_step
SYNOPSIS
void rv64_step(rv64_t* rv, slots_t* slots)
FUNCTION
Execute a single RISC-V instruction or processor state transition.
INPUTS
rv Pointer to the RISC-V state structure for this virtual
processor.
slots Pointer to a slots_t which contains the memory map accessible
to the virtual RISC-V processor.
RESULT
SEE ALSO
rv64/rv64_run_until_trap