Skip to content

Commit

Permalink
Implement riscv_hart_run_userland()
Browse files Browse the repository at this point in the history
- Needed for Userland API, separated into HART module
- Where should the PC increment happen? In UserlandVM, merely returning from riscv_trap() means we land on a next instruction after the one that triggered the trap. This implementation preserves this behavior, but may need some re-arrangement. For example, we can increment the PC on the next entry to riscv_hart_run_userland(), or perhaps defer this to outside code (Will require changes on UserlandVM side)
  • Loading branch information
LekKit authored Nov 18, 2022
1 parent d175f08 commit d20c2d2
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 22 deletions.
51 changes: 36 additions & 15 deletions src/riscv_hart.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,19 @@ void riscv_hart_run(rvvm_hart_t* vm)
}
}

rvvm_addr_t riscv_hart_run_userland(rvvm_hart_t* vm)
{
vm->user_traps = true;
atomic_store_uint32(&vm->wait_event, HART_RUNNING);
#ifdef USE_SJLJ
setjmp(vm->unwind);
#endif
if (atomic_load_uint32(&vm->wait_event)) {
riscv_run_till_event(vm);
}
return vm->csr.cause[PRIVILEGE_USER];
}

#ifdef USE_RV64
void riscv_update_xlen(rvvm_hart_t* vm)
{
Expand Down Expand Up @@ -199,22 +212,30 @@ static void riscv_trap_priv_helper(rvvm_hart_t* vm, uint8_t target_priv)

void riscv_trap(rvvm_hart_t* vm, bitcnt_t cause, maxlen_t tval)
{
// Target privilege mode
uint8_t priv = PRIVILEGE_MACHINE;
// Delegate to lower privilege mode if needed
while ((priv > vm->priv_mode) && (vm->csr.edeleg[priv] & (1 << cause))) priv--;
//rvvm_info("Hart %p trap at %08"PRIxXLEN" -> %08"PRIxXLEN", cause %x, tval %08"PRIxXLEN"\n", vm, vm->registers[REGISTER_PC], vm->csr.tvec[priv] & (~3UL), cause, tval);
// Write exception info
vm->csr.epc[priv] = vm->registers[REGISTER_PC];
vm->csr.cause[priv] = cause;
vm->csr.tval[priv] = tval;
// Modify exception stack in csr.status
riscv_trap_priv_helper(vm, priv);
// Jump to trap vector, switch to target priv
vm->registers[REGISTER_PC] = vm->csr.tvec[priv] & (~3ULL);
vm->trap = true;
riscv_switch_priv(vm, priv);
if (cause < TRAP_ENVCALL_UMODE || cause > TRAP_ENVCALL_MMODE) riscv_jit_discard(vm);
if (cause < TRAP_ENVCALL_UMODE || cause > TRAP_ENVCALL_MMODE) {
riscv_jit_discard(vm);
}
if (vm->user_traps) {
// Defer usermode trap
vm->csr.cause[PRIVILEGE_USER] = cause;
vm->csr.tval[PRIVILEGE_USER] = tval;
} else {
// Target privilege mode
uint8_t priv = PRIVILEGE_MACHINE;
// Delegate to lower privilege mode if needed
while ((priv > vm->priv_mode) && (vm->csr.edeleg[priv] & (1 << cause))) priv--;
//rvvm_info("Hart %p trap at %08"PRIxXLEN" -> %08"PRIxXLEN", cause %x, tval %08"PRIxXLEN"\n", vm, vm->registers[REGISTER_PC], vm->csr.tvec[priv] & (~3UL), cause, tval);
// Write exception info
vm->csr.epc[priv] = vm->registers[REGISTER_PC];
vm->csr.cause[priv] = cause;
vm->csr.tval[priv] = tval;
// Modify exception stack in csr.status
riscv_trap_priv_helper(vm, priv);
// Jump to trap vector, switch to target priv
vm->registers[REGISTER_PC] = vm->csr.tvec[priv] & (~3ULL);
riscv_switch_priv(vm, priv);
}
#ifdef USE_SJLJ
longjmp(vm->unwind, 1);
#else
Expand Down
10 changes: 6 additions & 4 deletions src/riscv_hart.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ void riscv_hart_free(rvvm_hart_t* vm);

/* Hart-thread routines */

/*
* Executes the hart in a current thread
* Returns upon receiving EXT_EVENT_PAUSE
*/
// Executes the hart in a current thread
// Returns upon receiving EXT_EVENT_PAUSE
void riscv_hart_run(rvvm_hart_t* vm);

// Execute a userland context in current thread
// Returns trap cause upon any CPU trap
rvvm_addr_t riscv_hart_run_userland(rvvm_hart_t* vm);

// Correctly applies side-effects of switching privileges
void riscv_switch_priv(rvvm_hart_t* vm, uint8_t priv_mode);

Expand Down
13 changes: 10 additions & 3 deletions src/rvvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,11 @@ struct rvvm_hart_t {
uint8_t priv_mode;
bool rv64;
bool trap;
maxlen_t trap_pc;

bool user_traps;

bool lrsc;
maxlen_t lrsc_cas;

struct {
maxlen_t hartid;
Expand All @@ -231,8 +235,6 @@ struct rvvm_hart_t {
maxlen_t ip;
maxlen_t fcsr;
} csr;
maxlen_t lrsc_cas;
bool lrsc;
#ifdef USE_JIT
rvjit_block_t jit;
bool jit_enabled;
Expand Down Expand Up @@ -264,9 +266,14 @@ struct rvvm_machine_t {
rvfile_t* bootrom_file;
rvfile_t* kernel_file;
rvfile_t* dtb_file;

rvvm_reset_handler_t on_reset;
void* reset_data;

paddr_t dtb_addr;

plic_ctx_t* plic;
pci_bus_t* pci_bus;
#ifdef USE_FDT
// FDT nodes for device tree generation
struct fdt_node* fdt;
Expand Down

0 comments on commit d20c2d2

Please sign in to comment.