diff --git a/src/rvvm_user.c b/src/rvvm_user.c
index c7f35ebf2..b683e937e 100644
--- a/src/rvvm_user.c
+++ b/src/rvvm_user.c
@@ -46,6 +46,7 @@ along with this program. If not, see .
//#define RVVM_USER_TEST
//#define RVVM_USER_TEST_X86
+//#define RVVM_USER_TEST_RISCV
// Guard this for now
#if defined(__linux__) && defined(RVVM_USER_TEST)
@@ -76,6 +77,12 @@ along with this program. If not, see .
#include
#include
#include
+#include
+
+// Put syscall headers here
+#include /* Definition of FUTEX_* constants */
+#include /* Definition of SYS_* constants */
+#include
// Describes the executable to be ran
typedef struct {
@@ -213,6 +220,14 @@ static void* emulated_brk(void* addr)
return brk_ptr;
}
+// This is for debugging sake
+static elf_desc_t elf = {
+ .base = NULL,
+};
+static elf_desc_t interp = {
+ .base = NULL,
+};
+
// Main execution loop (Run the user CPU, handle syscalls)
void* rvvm_user_thread(void* arg)
{
@@ -266,10 +281,10 @@ void* rvvm_user_thread(void* arg)
rvvm_info("sys_pipe2(%lx, %lx)", a0, a1);
a0 = errno_ret(pipe2((void*)a0, a1));
break;
- /*case 61: // getdents64
+ case 61: // getdents64
rvvm_info("sys_getdents64(%ld, %lx, %lx)", a0, a1, a2);
- a0 = errno_ret()
- break;*/
+ a0 = syscall(SYS_getdents64, a0, a1, a2);
+ break;
case 62: // lseek
rvvm_info("sys_lseek(%ld, %lx, %lx)", a0, a1, a2);
a0 = errno_ret(lseek(a0, a1, a2));
@@ -318,6 +333,10 @@ void* rvvm_user_thread(void* arg)
rvvm_warn("sys_set_tid_address(%lx)", a0);
a0 = -38; // ENOSYS
break;
+ case 98: // futex
+ rvvm_info("sys_futex(%lx, %lx, %lx, %lx, %lx, %lx)", a0, a1, a2, a3, a4, a5);
+ a0 = syscall(SYS_futex, a0, a1, a2, a3, a4, a5);
+ break;
case 99: // set_robust_list
rvvm_warn("sys_set_robust_list(%lx, %lx)", a0, a1);
a0 = -38; // ENOSYS
@@ -372,13 +391,17 @@ void* rvvm_user_thread(void* arg)
.sysname = "Linux",
.nodename = "rvvm-user",
.release = "6.6.6",
- .version = "RVVM "RVVM_VERSION,
+ .version = "RVVM " RVVM_VERSION,
.machine = "riscv64",
};
memcpy((void*)a0, &name, sizeof(name));
a0 = 0;
}
break;
+ case 167: // prctl
+ rvvm_info("sys_prctl(%lx, %lx, %lx, %lx, %lx)", a0, a1, a2, a3, a4);
+ a0 = errno_ret(prctl(a0, a1, a2, a3, a4));
+ break;
case 172: // getpid
rvvm_info("sys_getpid()");
a0 = errno_ret(getpid());
@@ -470,13 +493,35 @@ void* rvvm_user_thread(void* arg)
}
rvvm_info(" -> %lx", a0);
rvvm_write_cpu_reg(cpu, RVVM_REGID_X0 + 10, a0);
+ rvvm_write_cpu_reg(cpu, RVVM_REGID_PC, rvvm_read_cpu_reg(cpu, RVVM_REGID_PC) + 4);
} else {
- uint8_t* pc = (uint8_t*)(size_t)rvvm_read_cpu_reg(cpu, RVVM_REGID_PC);
- rvvm_warn("Exception at PC %p", pc);
- rvvm_warn("SP: %lx", rvvm_read_cpu_reg(cpu, RVVM_REGID_X0 + 2));
- rvvm_warn("CAUSE: %lx", rvvm_read_cpu_reg(cpu, RVVM_REGID_CAUSE));
- rvvm_warn("TVAL: %lx", rvvm_read_cpu_reg(cpu, RVVM_REGID_TVAL));
- rvvm_warn("insn bytes: %02x%02x%02x%02x", pc[0], pc[1], pc[2], pc[3]);
+ // Boom!
+ rvvm_warn("Exception %lx (tval %lx) at PC %lx, SP %lx",
+ rvvm_read_cpu_reg(cpu, RVVM_REGID_CAUSE),
+ rvvm_read_cpu_reg(cpu, RVVM_REGID_TVAL),
+ rvvm_read_cpu_reg(cpu, RVVM_REGID_PC),
+ rvvm_read_cpu_reg(cpu, RVVM_REGID_X0 + 2));
+ for (uint32_t i=0; i<32; ++i) {
+ rvvm_warn("X%d: %016lx", i, rvvm_read_cpu_reg(cpu, RVVM_REGID_X0 + i));
+ }
+
+ rvvm_addr_t pc = rvvm_read_cpu_reg(cpu, RVVM_REGID_PC);
+ rvvm_addr_t pc_al = EVAL_MAX(pc - 16, pc & ~0xFFF);
+ rvvm_warn("Instruction bytes around PC:");
+ for (size_t i=0; i<32; ++i) {
+ printf("%02x", *(uint8_t*)(pc_al + i));
+ }
+ printf("\n");
+ for (size_t i=0; i<32; ++i) {
+ printf("%s", (pc_al + i == pc) ? "^ " : " ");
+ }
+ printf("\n");
+ if (pc >= (size_t)elf.base && pc < (size_t)elf.base + elf.buf_size) {
+ rvvm_warn("Crash inside main binary, reloc: %lx", pc - (size_t)elf.base);
+ }
+ if (pc >= (size_t)interp.base && pc < (size_t)interp.base + interp.buf_size) {
+ rvvm_warn("Crash inside interpreter, reloc: %lx", pc - (size_t)interp.base);
+ }
break;
}
}
@@ -486,7 +531,17 @@ void* rvvm_user_thread(void* arg)
// Jump into _start after setting up the context
static void jump_start(void* entry, void* stack_top)
{
-#ifdef RVVM_USER_TEST_X86
+#ifdef RVVM_USER_TEST_RISCV
+ register size_t a0 __asm__("a0") = (size_t) entry;
+ register size_t sp __asm__("sp") = (size_t) stack_top;
+
+ __asm__ __volatile__(
+ "jr a0;"
+ :
+ : "r" (a0), "r" (sp)
+ :
+ );
+#elif defined(RVVM_USER_TEST_X86)
register size_t rax __asm__("rax") = (size_t) entry;
register size_t rsp __asm__("rsp") = (size_t) stack_top;
register size_t rdx __asm__("rdx") = (size_t) &exit; // Why do we even need to pass this?
@@ -512,12 +567,12 @@ static void jump_start(void* entry, void* stack_top)
int rvvm_user(int argc, const char** argv, const char** envp)
{
- elf_desc_t elf = {
+ /*elf_desc_t elf = {
.base = NULL,
};
elf_desc_t interp = {
.base = NULL,
- };
+ };*/
rvfile_t* file = rvopen(argv[0], 0);
bool success = file && elf_load_file(file, &elf);
rvclose(file);