commit 52a430f311f2ce1fe38eb2fb7d5867df29e13e7e from: Benjamin Stürz date: Sun Feb 18 12:28:22 2024 UTC port to 64 bit commit - 5f8048ab7e609ab2283a4a1e9a4e74276ec1f547 commit + 52a430f311f2ce1fe38eb2fb7d5867df29e13e7e blob - b862efd1a319407c20f8397f6fa3a7b6fd65b9b9 blob + 2739ea77906d91f6c1a52c00b357948a4c7390ef --- .gitignore +++ .gitignore @@ -2,5 +2,7 @@ *.core *.o *.elf +rootfs +syscalls.h rvemu blob - c683707ec93490fb754776ec570d1ce24be25248 blob + 6634c2708ac436e52f5c1fb974b170cf6de574cb --- Makefile +++ Makefile @@ -2,24 +2,41 @@ .SUFFIXES: .SUFFIXES: .c .S .o .elf -CROSS = riscv32-unknown-linux-musl -CFLAGS = -fno-PIC -O3 -LDFLAGS = -s -Wl,--image-base,0x78000000 -no-pie -static -lpthread -lutil -OBJ = rvemu.o syscall.o cpu.o exec.o +SUDO = doas +PREFIX = /usr/local + +CROSS = riscv64-unknown-linux-musl +CFLAGS = -fPIC -O3 +LDFLAGS = -s -pie -static -lpthread +OBJ = rvemu.o ecall.o cpu.o exec.o PROGS = test.elf hello.elf all: rvemu ${PROGS} clean: - rm -f rvemu *.o *.elf *.core + rm -f rvemu *.o *.elf *.core syscalls.h + rm -rf rootfs -run: rvemu test.elf - ./rvemu test.elf +install: rvemu + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f rvemu ${DESTDIR}${PREFIX}/bin/ +run: rvemu ${PROGS} + mkdir -p rootfs/bin + cp -f rvemu rootfs/bin + cp -f ${PROGS} rootfs + ${SUDO} chroot rootfs /bin/rvemu /test.elf + rvemu: ${OBJ} ${CC} -o $@ ${OBJ} ${LDFLAGS} +ecall.o: syscalls.h + +syscalls.h: syscalls.inc + sed 's/^\.set \(SYS_[a-z0-9_]*\), \([0-9]*\)$$/#define \1 \2/' \ + < syscalls.inc > syscalls.h + .c.o: rvemu.h ${CC} -c -o $@ $< ${CFLAGS} blob - be1763527ea5c72f4c66c475b65c59b496befb2e blob + f12b40ff570310c03a64afafdf2dcb151c7f4878 --- cpu.c +++ cpu.c @@ -1,16 +1,15 @@ #include "rvemu.h" -static u32 regs[31]; -u32 pc; +static u64 regs[31]; +u64 pc; - -void cpu_set (size_t reg, u32 val) +void cpu_set (size_t reg, u64 val) { if (reg > 0) regs[reg - 1] = val; } -u32 cpu_get (size_t reg) +u64 cpu_get (size_t reg) { return reg > 0 ? regs[reg - 1] : 0; } @@ -23,6 +22,11 @@ u32 cpu_fetch (void) return i; } +static i64 extend (i32 x) +{ + return x; +} + void cpu_exec (u32 instr) { const char *name; @@ -31,19 +35,20 @@ void cpu_exec (u32 instr) const u8 rs1 = (instr >> 15) & 0x1f; const u8 rs2 = (instr >> 20) & 0x1f; const u8 funct7 = instr >> 25; - const u32 imm_i = (i32)instr >> 20; - const u32 imm_s = ((i32)instr >> 25 << 5) | ((instr >> 7) & 0x1f); - const u32 imm_b = (instr >> 31 << 12) + const u64 imm_i = extend ((i32)instr >> 20); + const u64 imm_s = extend (((i32)instr >> 25 << 5) | ((instr >> 7) & 0x1f)); + const u64 imm_b = extend (((i32)instr >> 31 << 12) | (((instr >> 25) & 0x3f) << 5) | (((instr >> 8) & 0xf) << 1) - | (((instr >> 7) & 1) << 11); - const u32 imm_u = instr & 0xfffff000; - const u32 imm_j = ((i32)instr >> 31 << 20) + | (((instr >> 7) & 1) << 11)); + const u64 imm_u = extend (instr & 0xfffff000); + const u64 imm_j = extend (((i32)instr >> 31 << 20) | (((instr >> 21) & 0x3ff) << 1) | (((instr >> 20) & 1) << 11) - | (((instr >> 12) & 0xff) << 12); + | (((instr >> 12) & 0xff) << 12)); + const u8 shamt = imm_i & 0x3f; - u32 a, b, c; + u64 a, b, c; switch (instr & 0x7f) { case 0b0110111: // lui rd, uimm eprintf ("lui x%u, %u\n", (uint)rd, imm_u); @@ -78,11 +83,11 @@ void cpu_exec (u32 instr) c = a != b; case 0b100: name = "blt"; - c = (i32)a < (i32)b; + c = (i64)a < (i64)b; break; case 0b101: name = "bge"; - c = (i32)a >= (i32)b; + c = (i64)a >= (i64)b; break; case 0b110: name = "bltu"; @@ -104,16 +109,20 @@ void cpu_exec (u32 instr) switch (funct3) { case 0b000: // lb name = "lb"; - b = (i32)read_i8 (a); + b = (i64)read_i8 (a); break; case 0b001: // lh name = "lh"; - b = (i32)read_i16 (a); + b = (i64)read_i16 (a); break; case 0b010: // lw name = "lw"; - b = read_u32 (a); + b = (i64)read_i32 (a); break; + case 0b011: // ld + name = "ld"; + b = read_u64 (a); + break; case 0b100: // lbu name = "lbu"; b = read_u8 (a); @@ -122,6 +131,10 @@ void cpu_exec (u32 instr) name = "lhu"; b = read_u16 (a); break; + case 0b110: // lwu + name = "lwu"; + b = read_u32 (a); + break; default: goto ud; } @@ -144,6 +157,10 @@ void cpu_exec (u32 instr) name = "sw"; write_u32 (b, a); break; + case 0b011: // sd + name = "sd"; + write_u64 (b, a); + break; default: goto ud; } @@ -159,11 +176,11 @@ void cpu_exec (u32 instr) break; case 0b001: // slli name = "slli"; - c = a << (b & 0x1f); + c = a << shamt; break; case 0b010: // slti name = "slti"; - c = (i32)a < (i32)b; + c = (i64)a < (i64)b; break; case 0b011: // sltiu name = "sltiu"; @@ -176,10 +193,10 @@ void cpu_exec (u32 instr) case 0b101: // srli/srai if ((instr >> 30) & 1) { name = "srai"; - c = (i32)a >> b; + c = (i64)a >> shamt; } else { name = "srli"; - c = a >> b; + c = a >> shamt; } break; case 0b110: // ori @@ -193,7 +210,41 @@ void cpu_exec (u32 instr) default: goto ud; } - eprintf ("%s x%u, x%u, %d\n", name, (uint)rd, (uint)rs1, (int)imm_i); + eprintf ("%s x%u, x%u, %lld\n", name, (uint)rd, (uint)rs1, (i64)imm_i); + cpu_set (rd, c); + break; + case 0b0011011: // aluiw rd, rs1, iimm + a = cpu_get (rs1); + b = imm_i; + c = (instr >> 30) & 1; + switch (funct3) { + case 0b000: // addiw + name = "addiw"; + c = a + b; + break; + case 0b001: // slliw + if (shamt >> 5) + goto ud; + name = "slliw"; + c = a << shamt; + break; + case 0b101: // srliw/sraiw + if (shamt >> 5) + goto ud; + if (c) { + name = "srai"; + c = (i64)a >> shamt; + } else { + name = "srli"; + c = a >> shamt; + } + break; + default: + goto ud; + } + c &= 0x00000000ffffffff; + c = extend (c); + eprintf ("%s x%u, x%u, %lld\n", name, (uint)rd, (uint)rs1, (i64)imm_i); cpu_set (rd, c); break; case 0b0110011: // alu rd, rs1, rs2 @@ -216,7 +267,7 @@ void cpu_exec (u32 instr) break; case 0b010: // slt name = "slt"; - a = (i32)a < (i32)b; + a = (i64)a < (i64)b; break; case 0b011: // sltu name = "sltu"; @@ -229,10 +280,10 @@ void cpu_exec (u32 instr) case 0b101: // srl/sra if (c) { name = "sra"; - a = (i32)a >> b; + a = (i64)a >> (b & 0x3f); } else { name = "srl"; - a >>= b; + a >>= (b & 0x3f); } break; case 0b110: // or @@ -247,6 +298,39 @@ void cpu_exec (u32 instr) eprintf ("%s x%u, x%u, x%u\n", name, (uint)rd, (uint)rs1, (uint)rs2); cpu_set (rd, a); break; + case 0b0111011: // aluw + a = cpu_get (rs1); + b = cpu_get (rs2); + c = (instr >> 30) & 1; + switch (funct3) { + case 0b000: // addw/subw + if (c) { + name = "subw"; + c = a - b; + } else { + name = "addw"; + c = a + b; + } + break; + case 0b001: // sllw + name = "sllw"; + c = a << (b & 0x1f); + break; + case 0b101: // srlw/sraiw + if (c) { + name = "sraw"; + c = (i64)a >> (b & 0x1f); + } else { + name = "srlw"; + c = a >> (b & 0x1f); + } + break; + default: + goto ud; + } + eprintf ("%s x%u, x%u, x%u\n", name, (uint)rd, (uint)rs1, (uint)rs2); + cpu_set (rd, extend ((i32)a)); + break; case 0b0001111: // fence/fence.tso/pause eprintf ("fence\n"); break; @@ -265,7 +349,7 @@ void cpu_exec (u32 instr) break; default: ud: - errx (1, "%08x: invalid instruction: %08x", pc - 4, instr); + errx (1, "%08llx: invalid instruction: %08x", pc - 4, instr); } } blob - 7f8efcda3a12cf5aff8ecfa2b29bb63f61b90cd3 blob + 66eb875ea57dc87a40bf8b6cb2d3386f35feeb06 --- exec.c +++ exec.c @@ -7,33 +7,19 @@ #include "rvemu.h" -int is_executable (const Elf32_Ehdr *ehdr) +int is_executable (const Elf64_Ehdr *ehdr) { return IS_ELF (*ehdr) - && ehdr->e_ident[EI_CLASS] == ELFCLASS32 + && ehdr->e_ident[EI_CLASS] == ELFCLASS64 && ehdr->e_ident[EI_DATA] == ELFDATA2LSB && ehdr->e_machine == EM_RISCV ; } -static char **copyv (u32 v) +int my_execve (const char *path, char **argv, char **envp) { - char **a; - int n; - for (n = 0; read_u32 (v + n * 4) != 0; ++n); - - a = calloc (n + 1, sizeof (char *)); - for (int i = 0; i < n; ++i) - a[i] = (char *)(size_t)read_u32 (v + i * 4); - - return a; -} - -int my_execve (const char *path, u32 argv, u32 envp) -{ - - Elf32_Ehdr ehdr; + Elf64_Ehdr ehdr; char buffer[256], *nl, *s, **args, **env; int fd; @@ -68,13 +54,10 @@ int my_execve (const char *path, u32 argv, u32 envp) read (fd, &ehdr, sizeof (ehdr)); close (fd); - args = copyv (argv); - env = copyv (envp); - if (is_executable (&ehdr)) { - path = interpreter; + return execvpe ("rvemu", argv, envp); } - return execve (path, args, env); + return execve (path, argv, envp); } blob - /dev/null blob + f2631d600322b6a3bc1d74865ef5cd3f54fe743a (mode 644) --- /dev/null +++ ecall.c @@ -0,0 +1,964 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "syscalls.h" +#include "rvemu.h" + +struct linux_stat64 { + u64 dev; + u64 ino; + u32 mode; + u32 nlink; + u32 uid; + u32 gid; + u64 rdev; + u64 __pad1; + u64 size; + u32 blksize; + u32 __pad2; + u64 blocks; + u32 atime; + u32 atime_ns; + u32 mtime; + u32 mtime_ns; + u32 ctime; + u32 ctime_ns; + u32 __unused4; + u32 __unused5; +}; + +struct linux_utsname { + char sysname[65]; + char nodename[65]; + char release[65]; + char version[65]; + char machine[65]; +}; + +static int map_errno (int err) +{ + const int errnos[] = { + [EPERM] = 1, + [ENOENT] = 2, + [ESRCH] = 3, + [EINTR] = 4, + [EIO] = 5, + [ENXIO] = 6, + [E2BIG] = 7, + [ENOEXEC] = 8, + [EBADF] = 9, + [ECHILD] = 10, + [EAGAIN] = 11, + [ENOMEM] = 12, + [EACCES] = 13, + [EFAULT] = 14, + [ENOTBLK] = 15, + [EBUSY] = 16, + [EEXIST] = 17, + [EXDEV] = 18, + [ENODEV] = 19, + [ENOTDIR] = 20, + [EISDIR] = 21, + [EINVAL] = 22, + [ENFILE] = 23, + [EMFILE] = 24, + [ENOTTY] = 25, + [ETXTBSY] = 26, + [EFBIG] = 27, + [ENOSPC] = 28, + [ESPIPE] = 29, + [EROFS] = 30, + [EMLINK] = 31, + [EPIPE] = 32, + [EDOM] = 33, + [ERANGE] = 34, + [EDEADLK] = 35, + [ENAMETOOLONG] = 36, + [ENOLCK] = 37, + [ENOSYS] = 38, + }; + return errnos[err]; +} + +static int map (int x) { + return x < 0 ? -map_errno (errno) : x; +} + + +static void stat_to_linux_stat (struct linux_stat64 *lst, const struct stat *st) +{ + memset (lst, 0, sizeof (*lst)); + lst->dev = st->st_dev; + lst->ino = st->st_dev; + lst->mode = st->st_dev; + lst->nlink = st->st_dev; + lst->uid = st->st_dev; + lst->gid = st->st_dev; + lst->rdev = st->st_dev; + lst->size = st->st_dev; + lst->blksize = st->st_dev; + lst->blocks = st->st_dev; + lst->atime = st->st_atim.tv_sec; + lst->atime_ns = st->st_atim.tv_nsec; + lst->mtime = st->st_mtim.tv_sec; + lst->mtime_ns = st->st_mtim.tv_nsec; + lst->ctime = st->st_ctim.tv_sec; + lst->ctime_ns = st->st_ctim.tv_nsec; +} + +static void utsname_to_linux_utsname (struct linux_utsname *lun, const struct utsname *un) +{ + memset (lun, 0, sizeof (*lun)); + strlcpy (lun->sysname, un->sysname, 65); + strlcpy (lun->nodename, un->nodename, 65); + strlcpy (lun->release, un->release, 65); + strlcpy (lun->version, un->version, 65); + strlcpy (lun->machine, un->machine, 65); +} + +static int enosys (const char *sys) +{ + warnx ("unimplemented syscall: %s", sys); + return -map_errno (ENOSYS); +} + +static u64 my_brk (u64 new) +{ + void *ptr; + + if (new < brkval) + return brkval; + if (new >= 0x78000000) { + errno = ENOMEM; + return -1; + } + + new = (new + 4095) & ~0x3ff; + ptr = mmap ( + (void *)brkval, + new - brkval, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, + -1, + 0 + ); + if (ptr == NULL) + return -1; + brkval = new; + return brkval; +} + +#define ptr(T, x) ((T *)(x)) +#define str(x) ptr (const char, x) +void ecall (void) +{ + struct linux_stat64 lst; + struct linux_utsname lun; + struct stat st; + struct utsname un; + void *ptr; + const u64 a0 = cpu_get (10); + const u64 a1 = cpu_get (11); + const u64 a2 = cpu_get (12); + const u64 a3 = cpu_get (13); + const u64 a4 = cpu_get (14); + const u64 a5 = cpu_get (15); + const u64 a7 = cpu_get (17); + u64 ret; + switch (a7) { + case SYS_getcwd: + ret = enosys ("getcwd"); + break; + case SYS_dup: + ret = map (dup ((int)a0)); + break; + case SYS_dup3: + ret = map (dup3 ((int)a0, (int)a1, (int)a2)); + break; + case SYS_fcntl: + ret = enosys ("fcntl"); + break; + case SYS_ioctl: + ret = enosys ("ioctl"); + break; + case SYS_flock: + ret = map (flock ((int)a0, (int)a1)); + break; + case SYS_mknodat: + ret = map (mknodat ((int)a0, str (a1), (mode_t)a2, (dev_t)a3)); + + case SYS_mkdirat: + ret = map (mkdirat ((int)a0, str (a1), (mode_t)a2)); + break; + case SYS_unlinkat: + ret = map (unlinkat ((int)a0, str (a1), (int)a2)); + break; + case SYS_symlinkat: + ret = map (symlinkat (str (a0), (int)a1, str (a2))); + break; + case SYS_linkat: + ret = map (linkat ((int)a0, str (a1), (int)a2, str (a3), (int)a4)); + break; + case SYS_renameat: + ret = map (renameat ((int)a0, str (a1), (int)a2, str (a3))); + break; + case SYS_umount: + ret = enosys ("umount"); + break; + case SYS_mount: + ret = enosys ("mount"); + break; + case SYS_pivot_root: + ret = enosys ("pivot_root"); + break; + case SYS_nfsservctl: + ret = enosys ("nfsservctl"); + break; + case SYS_statfs: + ret = enosys ("statfs"); + break; + case SYS_fstatfs: + ret = enosys ("fstatfs"); + break; + case SYS_truncate: + ret = map (truncate (str (a0), (off_t)a1)); + break; + break; + case SYS_ftruncate: + ret = map (ftruncate ((int)a0, (off_t)a1)); + break; + case SYS_fallocate: + ret = enosys ("fallocate"); + break; + case SYS_faccessat: + ret = map (faccessat ((int)a0, str (a1), (int)a2, (int)a3)); + break; + case SYS_chdir: + ret = map (chdir (str (a0))); + break; + case SYS_fchdir: + ret = map (fchdir ((int)a0)); + break; + case SYS_chroot: + ret = map (chroot (str (a0))); + break; + case SYS_fchmod: + ret = map (fchmod ((int)a0, (mode_t)a1)); + break; + case SYS_fchmodat: + ret = map (fchmodat ((int)a0, str (a1), (mode_t)a2, (int)a3)); + break; + case SYS_fchownat: + ret = map (fchownat ((int)a0, str (a1), (uid_t)a2, (gid_t)a3, (int)a4)); + break; + case SYS_fchown: + ret = map (fchown ((int)a0, (uid_t)a1, (gid_t)a2)); + break; + case SYS_openat: + ret = map (openat ((int)a0, str (a1), (int)a2, (int)a3)); + break; + case SYS_close: + ret = map (close ((int)a0)); + break; + case SYS_vhangup: + ret = enosys ("vhangup"); + break; + case SYS_pipe2: + ret = map (pipe2 (ptr (int, a0), (int)a1)); + break; + case SYS_quotactl: + ret = enosys ("quotactl"); + break; + case SYS_getdents64: + ret = enosys ("getdents64"); + break; + case SYS_lseek: + ret = map (lseek ((int)a0, (off_t)a1, (int)a2)); + break; + case SYS_read: + ret = map (read ((int)a0, ptr (void, a1), (size_t)a2)); + break; + case SYS_write: + ret = map (write ((int)a0, ptr (const void, a1), (size_t)a2)); + break; + case SYS_readv: + ret = enosys ("readv"); + break; + case SYS_writev: + ret = enosys ("writev"); + break; + case SYS_pread: + ret = map (pread ((int)a0, ptr (void, a1), (size_t)a2, (off_t)a3)); + break; + case SYS_pwrite: + ret = map (pwrite ((int)a0, ptr (const void, a1), (size_t)a2, (off_t)a3)); + break; + case SYS_preadv: + ret = enosys ("preadv"); + break; + case SYS_pwritev: + ret = enosys ("pwritev"); + break; + case SYS_sendfile: + ret = enosys ("sendfile"); + break; + case SYS_pselect6: + ret = enosys ("pselect6"); + break; + case SYS_ppoll: + ret = enosys ("ppoll"); + break; + case SYS_signalfd4: + ret = enosys ("signalfd4"); + break; + case SYS_vmsplice: + ret = enosys ("vmsplice"); + break; + case SYS_splice: + ret = enosys ("splice"); + break; + case SYS_tee: + ret = enosys ("tee"); + break; + case SYS_readlinkat: + ret = map (readlinkat ((int)a0, str (a1), ptr (char, a2), (size_t)a3)); + break; + case SYS_fstatat: + ret = map (fstatat ((int)a0, str (a1), &st, (int)a3)); + stat_to_linux_stat (&lst, &st); + memcpy (ptr (void, a2), &lst, sizeof (lst)); + break; + case SYS_fstat: + ret = map (fstat ((int)a0, &st)); + stat_to_linux_stat (&lst, &st); + memcpy (ptr (void, a1), &lst, sizeof (lst)); + break; + case SYS_sync: + sync (); + ret = 0; + break; + case SYS_fsync: + ret = map (fsync ((int)a0)); + break; + case SYS_fdatasync: + ret = map (fdatasync ((int)a0)); + break; + case SYS_sync_file_range: + ret = enosys ("sync_file_range"); + break; + case SYS_timerfd_create: + ret = enosys ("timerfd_create"); + break; + case SYS_timerfd_settime: + ret = enosys ("timerfd_settime"); + break; + case SYS_timerfd_gettime: + ret = enosys ("timerfd_gettime"); + break; + case SYS_utimensat: + ret = enosys ("utimensat"); + break; + case SYS_acct: + ret = acct (str (a0)); + break; + case SYS_capget: + ret = enosys ("capget"); + break; + case SYS_capset: + ret = enosys ("capset"); + break; + case SYS_personality: + ret = enosys ("personality"); + break; + case SYS_exit: + exit (a0); + ret = -1; + break; + case SYS_exit_group: + ret = enosys ("exit_group"); + break; + case SYS_waitid: + ret = enosys ("waitid"); + break; + case SYS_set_tid_address: + ret = enosys ("set_tid_address"); + break; + case SYS_unshare: + ret = enosys ("unshare"); + break; + case SYS_futex: + ret = enosys ("futex"); + break; + case SYS_set_robust_limit: + ret = enosys ("set_robust_limit"); + break; + case SYS_get_robust_limit: + ret = enosys ("get_robust_limit"); + break; + case SYS_nanosleep: + ret = enosys ("nanosleep"); + break; + case SYS_gettimer: + ret = enosys ("gettimer"); + break; + case SYS_settimer: + ret = enosys ("settimer"); + break; + case SYS_kexec_load: + ret = enosys ("kexec_load"); + break; + case SYS_kexec_init_module: + ret = enosys ("kexec_init_module"); + break; + case SYS_kexec_delete_module: + ret = enosys ("kexec_delete_module"); + break; + case SYS_timer_create: + ret = enosys ("timer_create"); + break; + case SYS_timer_gettime: + ret = enosys ("timer_gettime"); + break; + case SYS_timer_getoverrun: + ret = enosys ("timer_getoverrun"); + break; + case SYS_timer_settime: + ret = enosys ("timer_settime"); + break; + case SYS_timer_delete: + ret = enosys ("timer_delete"); + break; + case SYS_clock_settime: + ret = enosys ("clock_settime"); + break; + case SYS_clock_gettime: + ret = enosys ("clock_gettime"); + break; + case SYS_clock_getres: + ret = enosys ("clock_getres"); + break; + case SYS_clock_nanosleep: + ret = enosys ("clock_nanosleep"); + break; + case SYS_syslog: + ret = enosys ("syslog"); + break; + case SYS_ptrace: + ret = enosys ("ptrace"); + break; + case SYS_sched_setparam: + ret = enosys ("sched_setparam"); + break; + case SYS_sched_setscheduler: + ret = enosys ("sched_setscheduler"); + break; + case SYS_sched_getscheduler: + ret = enosys ("sched_getscheduler"); + break; + case SYS_sched_getparam: + ret = enosys ("sched_getparam"); + break; + case SYS_sched_setaffinity: + ret = enosys ("sched_setaffinity"); + break; + case SYS_sched_getaffinity: + ret = enosys ("sched_getaffinity"); + break; + case SYS_sched_yield: + ret = map (sched_yield ()); + break; + case SYS_sched_get_priority_max: + ret = map (sched_get_priority_max ((int)a0)); + break; + case SYS_sched_get_priority_min: + ret = map (sched_get_priority_min ((int)a0)); + break; + case SYS_sched_rr_get_interval: + ret = enosys ("sched_rr_get_interval"); + break; + case SYS_restart_syscall: + ret = enosys ("restart_syscall"); + break; + case SYS_kill: + ret = map (kill ((pid_t)a0, (int)a1)); + break; + case SYS_tkill: + ret = enosys ("tkill"); + break; + case SYS_tgkill: + ret = enosys ("tgkill"); + break; + case SYS_signalstack: + ret = enosys ("signalstack"); + break; + case SYS_sigsuspend: + ret = enosys ("sigsuspend"); + break; + case SYS_sigaction: + ret = enosys ("sigaction"); + break; + case SYS_rt_sigprocmask: + ret = enosys ("rt_sigprocmask"); + break; + case SYS_sigpending: + ret = enosys ("sigpending"); + break; + case SYS_sigtimedwait: + ret = enosys ("sigtimedwait"); + break; + case SYS_sigqueueinfo: + ret = enosys ("sigqueueinfo"); + break; + case SYS_sigreturn: + ret = enosys ("sigreturn"); + break; + case SYS_setpriority: + ret = map (setpriority ((int)a0, (id_t)a1, (int)a2)); + break; + case SYS_getpriority: + ret = map (getpriority ((int)a0, (id_t)a1)); + break; + case SYS_reboot: + ret = enosys ("reboot"); + break; + case SYS_setregid: + ret = map (setregid ((gid_t)a0, (gid_t)a1)); + break; + case SYS_setgid: + ret = map (setgid ((gid_t)a0)); + break; + case SYS_setreuid: + ret = map (setreuid ((uid_t)a0, (uid_t)a1)); + break; + case SYS_setuid: + ret = map (setuid ((uid_t)a0)); + break; + case SYS_setresuid: + ret = map (setresuid ((uid_t)a0, (uid_t)a1, (uid_t)a2)); + break; + case SYS_getresuid: + ret = map (getresuid (ptr (uid_t, a0), ptr (uid_t, a1), ptr (uid_t, a2))); + break; + case SYS_setresgid: + ret = map (setresgid ((gid_t)a0, (gid_t)a1, (gid_t)a2)); + break; + case SYS_getresgid: + ret = map (getresgid (ptr (gid_t, a0), ptr (gid_t, a1), ptr (gid_t, a2))); + break; + case SYS_setfsuid: + ret = enosys ("setfsuid"); + break; + case SYS_setfsgid: + ret = enosys ("setfsgid"); + break; + case SYS_times: + ret = enosys ("times"); + break; + case SYS_setpgid: + ret = map (setpgid ((pid_t)a0, (pid_t)a1)); + break; + case SYS_getpgid: + ret = map (getpgid ((pid_t)a0)); + break; + case SYS_getsid: + ret = map (getsid ((pid_t)a0)); + break; + case SYS_setsid: + ret = map (setsid ()); + break; + case SYS_setgroups: + ret = enosys ("setgroups"); + break; + case SYS_uname: + ret = map (uname (&un)); + utsname_to_linux_utsname (&lun, &un); + memcpy (ptr (void, a0), &lun, sizeof (lun)); + break; + case SYS_sethostname: + ret = enosys ("sethostname"); + break; + case SYS_setdomainname: + ret = enosys ("setdomainname"); + break; + case SYS_getrlimit: + ret = enosys ("getrlimit"); + break; + case SYS_setrlimit: + ret = enosys ("setrlimit"); + break; + case SYS_getrusage: + ret = enosys ("getrusage"); + break; + case SYS_umask: + ret = map (umask ((mode_t)a0)); + break; + case SYS_prctl: + ret = enosys ("prctl"); + break; + case SYS_getcpu: + ret = enosys ("getcpu"); + break; + case SYS_gettimeofday: + ret = enosys ("gettimeofday"); + break; + case SYS_settimeofday: + ret = enosys ("settimeofday"); + break; + case SYS_adjtimex: + ret = enosys ("adjtimex"); + break; + case SYS_getpid: + ret = map (getpid ()); + break; + case SYS_getuid: + ret = map (getuid ()); + break; + case SYS_geteuid: + ret = map (geteuid ()); + break; + case SYS_getgid: + ret = map (getgid ()); + break; + case SYS_getegid: + ret = map (getegid ()); + break; + case SYS_gettid: + ret = enosys ("gettid"); + break; + case SYS_sysinfo: + ret = enosys ("sysinfo"); + break; + case 180: + case 181: + case 182: + case 183: + case 184: + case 185: + ret = enosys ("mq_*"); + break; + case SYS_msgget: + ret = map(msgget ((key_t)a0, (int)a1)); + break; + case SYS_msgctl: + ret = enosys ("msgctl"); + break; + case SYS_msgrcv: + ret = map (msgrcv ((int)a0, ptr (void, a1), (size_t)a2, (long)a3, (int)a4)); + break; + case SYS_msgsnd: + ret = map (msgsnd ((int)a0, ptr (const void, a1), (size_t)a2, (int)a3)); + break; + case SYS_semget: + ret = map (semget ((key_t)a0, (int)a1, (int)a2)); + break; + case SYS_semctl: + ret = enosys ("semctl"); + break; + case SYS_semtimedop: + ret = enosys ("semtimedop"); + break; + case SYS_semop: + ret = enosys ("semop"); + break; + case 194: + case 195: + case 196: + case 197: + ret = enosys ("shm*"); + break; + case 198: + case 199: + case 200: + case 201: + case 202: + case 203: + case 204: + case 205: + case 206: + case 207: + case 208: + case 209: + case 210: + case 211: + case 212: + ret = enosys ("socket api"); + break; + case SYS_readahead: + ret = enosys ("readahead"); + break; + case SYS_brk: + ret = map (my_brk (a0)); + break; + case SYS_munmap: + ret = map (munmap (ptr (void, a0), (size_t)a1)); + break; + case SYS_mremap: + ret = enosys ("mremap"); + break; + case SYS_add_key: + ret = enosys ("add_key"); + break; + case SYS_request_key: + ret = enosys ("request_key"); + break; + case SYS_keyctl: + ret = enosys ("keyctl"); + break; + case SYS_clone: + if (a0 == 17 && a1 == 0) { + // fork + ret = map (fork ()); + } else { + ret = enosys ("clone"); + } + break; + case SYS_execve: + ret = map (my_execve (str (a0), ptr (char *, a1), ptr (char *, a2))); + break; + case SYS_mmap: + ptr = mmap (ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5); + if (ptr == NULL) { + ret = -map_errno (errno); + } else { + ret = (u64)ptr; + } + break; + case SYS_fadvise64: + ret = enosys ("fadvise64"); + break; + case SYS_swapon: + ret = enosys ("swapon"); + break; + case SYS_swapoff: + ret = enosys ("swapoff"); + break; + case SYS_mprotect: + ret = map (mprotect (ptr (void, a0), (size_t)a1, (int)a2)); + break; + case SYS_msync: + ret = map (msync (ptr (void, a0), (size_t)a1, (int)a2)); + break; + case SYS_mlock: + ret = map (mlock (ptr (void, a0), (size_t)a1)); + break; + case SYS_munlock: + ret = map (munlock (ptr (void, a0), (size_t)a1)); + break; + case SYS_mlockall: + ret = map (mlockall ((int)a0)); + break; + case SYS_munlockall: + ret = map (munlockall ()); + break; + case SYS_mincore: + ret = enosys ("mincore"); + break; + case SYS_madvise: + ret = map (madvise (ptr (void, a0), (size_t)a1, (int)a2)); + break; + case SYS_remap_file_pages: + ret = enosys ("remap_file_pages"); + break; + case SYS_mbind: + ret = enosys ("mbind"); + break; + case SYS_get_mempolicy: + ret = enosys ("get_mempolicy"); + break; + case SYS_set_mempolicy: + ret = enosys ("set_mempolicy"); + break; + case SYS_migrate_pages: + ret = enosys ("migrate_pages"); + break; + case SYS_move_pages: + ret = enosys ("move_pages"); + break; + case SYS_rt_tgsigqueueinfo: + ret = enosys ("rt_tgsigqueueinfo"); + break; + case SYS_perf_event_open: + ret = enosys ("perf_event_open"); + break; + case SYS_accept4: + ret = enosys ("accept4"); + break; + case SYS_recvmsg: + ret = enosys ("recvmsg"); + break; + case 244: + case 245: + case 246: + case 247: + case 248: + case 249: + case 250: + case 251: + case 252: + case 253: + case 254: + case 255: + case 256: + case 257: + case 258: + case 259: + ret = enosys ("arch-specific"); + break; + case 260: + ret = enosys ("wait4"); + break; + case SYS_prlimit64: + ret = enosys ("prlimit64"); + break; + case SYS_fanotify_init: + ret = enosys ("fanotify_init"); + break; + case SYS_fanotify_mark: + ret = enosys ("fanotify_mark"); + break; + case SYS_name_to_handle_at: + ret = enosys ("name_to_handle_at"); + break; + case SYS_open_by_handle_at: + ret = enosys ("open_by_handle_at"); + break; + case SYS_clock_adjtime: + ret = enosys ("clock_adjtime"); + break; + case SYS_syncfs: + ret = enosys ("syncfs"); + break; + case SYS_setns: + ret = enosys ("setns"); + break; + case SYS_sendmsg: + ret = enosys ("sendmsg"); + break; + case SYS_process_vm_readv: + ret = enosys ("process_vm_readv"); + break; + case SYS_process_vm_writev: + ret = enosys ("process_vm_writev"); + break; + case SYS_kcmp: + ret = enosys ("kcmp"); + break; + case SYS_finit_module: + ret = enosys ("finit_module"); + break; + case SYS_sched_setattr: + ret = enosys ("sched_setattr"); + break; + case SYS_sched_getattr: + ret = enosys ("sched_getattr"); + break; + case SYS_renameat2: + ret = enosys ("renameat2"); + break; + case SYS_seccomp: + ret = enosys ("seccomp"); + break; + case SYS_getrandom: + ret = enosys ("getrandom"); + break; + case SYS_memfd_create: + ret = enosys ("seccomp"); + break; + case SYS_bpf: + ret = enosys ("bpf"); + break; + case SYS_execveat: + ret = enosys ("execveat"); + break; + case SYS_userfaultfd: + ret = enosys ("usefaultfd"); + break; + case SYS_membarrier: + ret = enosys ("membarrier"); + break; + case SYS_mlock2: + ret = enosys ("mlock2"); + break; + case SYS_copy_file_range: + ret = enosys ("copy_file_range"); + break; + case SYS_preadv2: + ret = enosys ("preadv2"); + break; + case SYS_pwritev2: + ret = enosys ("pwritev2"); + break; + case SYS_pkey_mprotect: + ret = enosys ("pkey_mprotect"); + break; + case SYS_pkey_alloc: + ret = enosys ("pkey_alloc"); + break; + case SYS_pkey_free: + ret = enosys ("pkey_free"); + break; + case SYS_statx: + ret = enosys ("statx"); + break; + case SYS_io_pgetevents: + ret = enosys ("io_pgetevents"); + break; + case SYS_rseq: + ret = enosys ("rseq"); + break; + case SYS_kexec_file_load: + ret = enosys ("kexec_file_load"); + break; + case SYS_open: + ret = map (open ((const char *)(size_t)a0, (int)a1, (int)a2)); + break; + case SYS_link: + ret = map (link (str (a0), str (a1))); + break; + case SYS_unlink: + ret = map (unlink (str (a0))); + break; + case SYS_mkdir: + ret = map (mkdir (str (a0), (mode_t)a1)); + break; + case SYS_access: + ret = map (access (str (a0), (int)a1)); + break; + case SYS_stat: + ret = map (stat (str (a0), &st)); + stat_to_linux_stat (&lst, &st); + memcpy (ptr (void, a1), &lst, sizeof (lst)); + break; + case SYS_lstat: + ret = map (lstat (str (a0), &st)); + stat_to_linux_stat (&lst, &st); + memcpy (ptr (void, a1), &lst, sizeof (lst)); + break; + case SYS_time: + ret = enosys ("time"); + break; + case SYS_getmainvars: + ret = enosys ("getmainvars"); + break; + case SYS_debug: + fprintf (stderr, "DEBUG: %llu\n", a0); + ret = 0; + break; + default: + warnx ("%08llx: unimplemented syscall %llu", pc - 4, a7); + ret = -map_errno (ENOSYS); + break; + } + cpu_set (REG_a0, ret); +} + blob - 10f6646bd6ae37bf7de1a9d35d7eccec7fbf3f7d blob + f5eebd803603f22e5415e2c2dbd56c756d929182 --- rvemu.c +++ rvemu.c @@ -9,12 +9,11 @@ #include #include "rvemu.h" -const char *interpreter = "./rvemu"; -u32 brkval; +u64 brkval; static void load_image (const char *filename) { - Elf32_Ehdr ehdr; + Elf64_Ehdr ehdr; int fd; fd = open (filename, O_RDONLY); @@ -30,7 +29,7 @@ static void load_image (const char *filename) pc = ehdr.e_entry; for (unsigned i = 0; i < ehdr.e_phnum; ++i) { - Elf32_Phdr phdr; + Elf64_Phdr phdr; u32 flags = 0, end; void *ptr; @@ -49,11 +48,11 @@ static void load_image (const char *filename) case PT_NULL: break; case PT_LOAD: - eprintf ("loading %08x into %08x flags %x memsz %u\n", + eprintf ("loading %016llx into %016llx flags %x memsz %u\n", phdr.p_offset, phdr.p_vaddr, phdr.p_flags, phdr.p_memsz); if (phdr.p_filesz == phdr.p_memsz) { ptr = mmap ( - (void *)(size_t)phdr.p_vaddr, + (void *)phdr.p_vaddr, phdr.p_memsz, flags, MAP_PRIVATE | MAP_COPY, @@ -62,7 +61,7 @@ static void load_image (const char *filename) ); } else if (phdr.p_filesz == 0) { ptr = mmap ( - (void *)(size_t)phdr.p_vaddr, + (void *)phdr.p_vaddr, phdr.p_memsz, flags, MAP_ANON | MAP_PRIVATE, @@ -70,14 +69,14 @@ static void load_image (const char *filename) 0 ); } else { - errx (1, "%u: p_filesz: %u, p_memsz: %u", + errx (1, "%u: p_filesz: %llu, p_memsz: %llu", i, phdr.p_filesz, phdr.p_memsz); } - if ((size_t)ptr != (size_t)phdr.p_vaddr) + if ((u64)ptr != phdr.p_vaddr) err (1, "%u: failed to map program header", i); - end = (((u32)(size_t)ptr + phdr.p_memsz) + 4095) & ~0x3ff; + end = (((u64)ptr + phdr.p_memsz) + 4095) & ~0x3ff; if (end > brkval) brkval = end; break; @@ -93,26 +92,14 @@ static void load_image (const char *filename) close (fd); } -static void cpu_push (u32 val) +static void cpu_push (u64 val) { - cpu_set (2, cpu_get (2) - 4); - write_u32 (cpu_get (2), val); + cpu_set (REG_sp, cpu_get (REG_sp) - 8); + write_u64 (cpu_get (REG_sp), val); } -static void cpu_push_str (const char *ptr) -{ - if ((size_t)ptr > 0x80000000) { - const size_t len = strlen (ptr); - char *nptr = sbrk (len + 1); - memcpy (nptr, ptr, len + 1); - assert ((size_t)nptr < 0x80000000); - ptr = nptr; - } - cpu_push ((u32)(size_t)ptr); -} - static void setup_stack ( - u32 stack_size, + u64 stack_size, int argc, char **argv, int envc, @@ -122,9 +109,9 @@ static void setup_stack ( void *stack_bottom; // set stack pointer - cpu_set (2, 0x80000000); + cpu_set (REG_sp, 0x80000000); - stack_bottom = (void *)(size_t)(0x80000000 - stack_size); + stack_bottom = (void *)(u64)(0x80000000 - stack_size); ptr = mmap ( stack_bottom, stack_size, @@ -139,10 +126,10 @@ static void setup_stack ( cpu_push (0); for (int i = envc - 1; i >= 0; --i) - cpu_push_str (envp[i]); + cpu_push ((u64)envp[i]); cpu_push (0); for (int i = argc; i >= 0; --i) - cpu_push_str (argv[i]); + cpu_push ((u64)argv[i]); cpu_push (argc); } @@ -155,6 +142,8 @@ int main (int argc, char *argv[], char *envp[]) char *base; void *ptr; + eprintf ("&main = %p\n", &main); + base = basename (argv[0]); if (strcmp (base, "rvemu") == 0) { blob - 982df935a81ad7877a60e5f5f7198413aa9a8819 blob + f1fa870f78600a53528abcc226d280124e392286 --- rvemu.h +++ rvemu.h @@ -12,6 +12,41 @@ # define eprintf(...) #endif +enum { + REG_zero, + REG_ra, + REG_sp, + REG_gp, + REG_tp, + REG_t0, + REG_t1, + REG_t2, + REG_s0, + REG_s1, + REG_a0, + REG_a1, + REG_a2, + REG_a3, + REG_a4, + REG_a5, + REG_a6, + REG_a7, + REG_s2, + REG_s3, + REG_s4, + REG_s5, + REG_s6, + REG_s7, + REG_s8, + REG_s9, + REG_s10, + REG_s11, + REG_t3, + REG_t4, + REG_t5, + REG_t6, +}; + typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; @@ -24,17 +59,17 @@ typedef int64_t i64; typedef unsigned int uint; -extern u32 pc; -extern u32 brkval; +extern u64 pc; +extern u64 brkval; extern const char *interpreter; u32 cpu_fetch (void); -u32 cpu_get (size_t reg); -void cpu_set (size_t reg, u32 val); +u64 cpu_get (size_t reg); +void cpu_set (size_t reg, u64 val); void cpu_exec (u32 instr); void ecall (void); -int my_execve (const char *path, u32 argv, u32 envp); -int is_executable (const Elf32_Ehdr *); +int my_execve (const char *path, char **argv, char **envp); +int is_executable (const Elf64_Ehdr *); #define read_u8(ptr) (*(const u8 *)(size_t)(ptr)) #define read_u16(ptr) (*(const u16 *)(size_t)(ptr)) blob - 687d4a84e1e49fbedc28cb07e931e816c372b093 (mode 644) blob + /dev/null --- syscall.c +++ /dev/null @@ -1,965 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rvemu.h" - -struct linux_stat64 { - u64 dev; - u64 ino; - u32 mode; - u32 nlink; - u32 uid; - u32 gid; - u64 rdev; - u64 __pad1; - u64 size; - u32 blksize; - u32 __pad2; - u64 blocks; - u32 atime; - u32 atime_ns; - u32 mtime; - u32 mtime_ns; - u32 ctime; - u32 ctime_ns; - u32 __unused4; - u32 __unused5; -}; - -struct linux_utsname { - char sysname[65]; - char nodename[65]; - char release[65]; - char version[65]; - char machine[65]; -}; - -static int map_errno (int err) -{ - const int errnos[] = { - [EPERM] = 1, - [ENOENT] = 2, - [ESRCH] = 3, - [EINTR] = 4, - [EIO] = 5, - [ENXIO] = 6, - [E2BIG] = 7, - [ENOEXEC] = 8, - [EBADF] = 9, - [ECHILD] = 10, - [EAGAIN] = 11, - [ENOMEM] = 12, - [EACCES] = 13, - [EFAULT] = 14, - [ENOTBLK] = 15, - [EBUSY] = 16, - [EEXIST] = 17, - [EXDEV] = 18, - [ENODEV] = 19, - [ENOTDIR] = 20, - [EISDIR] = 21, - [EINVAL] = 22, - [ENFILE] = 23, - [EMFILE] = 24, - [ENOTTY] = 25, - [ETXTBSY] = 26, - [EFBIG] = 27, - [ENOSPC] = 28, - [ESPIPE] = 29, - [EROFS] = 30, - [EMLINK] = 31, - [EPIPE] = 32, - [EDOM] = 33, - [ERANGE] = 34, - [EDEADLK] = 35, - [ENAMETOOLONG] = 36, - [ENOLCK] = 37, - [ENOSYS] = 38, - }; - return errnos[err]; -} - -static int map (int x) { - return x < 0 ? -map_errno (errno) : x; -} - - -static void stat_to_linux_stat (struct linux_stat64 *lst, const struct stat *st) -{ - memset (lst, 0, sizeof (*lst)); - lst->dev = st->st_dev; - lst->ino = st->st_dev; - lst->mode = st->st_dev; - lst->nlink = st->st_dev; - lst->uid = st->st_dev; - lst->gid = st->st_dev; - lst->rdev = st->st_dev; - lst->size = st->st_dev; - lst->blksize = st->st_dev; - lst->blocks = st->st_dev; - lst->atime = st->st_atim.tv_sec; - lst->atime_ns = st->st_atim.tv_nsec; - lst->mtime = st->st_mtim.tv_sec; - lst->mtime_ns = st->st_mtim.tv_nsec; - lst->ctime = st->st_ctim.tv_sec; - lst->ctime_ns = st->st_ctim.tv_nsec; -} - -static void utsname_to_linux_utsname (struct linux_utsname *lun, const struct utsname *un) -{ - memset (lun, 0, sizeof (*lun)); - strlcpy (lun->sysname, un->sysname, 65); - strlcpy (lun->nodename, un->nodename, 65); - strlcpy (lun->release, un->release, 65); - strlcpy (lun->version, un->version, 65); - strlcpy (lun->machine, un->machine, 65); -} - -static int enosys (const char *sys) -{ - warnx ("unimplemented syscall: %s", sys); - return -map_errno (ENOSYS); -} - -static u32 my_brk (u32 new) -{ - void *ptr; - - if (new < brkval) - return brkval; - if (new >= 0x78000000) { - errno = ENOMEM; - return -1; - } - - new = (new + 4095) & ~0x3ff; - ptr = mmap ( - (void *)(size_t)brkval, - new - brkval, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, - -1, - 0 - ); - if (ptr == NULL) - return -1; - brkval = new; - return brkval; -} - -#define ptr(T, x) ((T *)(size_t)(x)) -#define str(x) ptr (const char, x) -void ecall (void) -{ - struct linux_stat64 lst; - struct linux_utsname lun; - struct stat st; - struct utsname un; - void *ptr; - const u32 a0 = cpu_get (10); - const u32 a1 = cpu_get (11); - const u32 a2 = cpu_get (12); - const u32 a3 = cpu_get (13); - const u32 a4 = cpu_get (14); - const u32 a5 = cpu_get (15); - const u32 a7 = cpu_get (17); - u32 ret; - switch (a7) { - case 17: // getcwd - ret = enosys ("getcwd"); - break; - case 23: // dup - ret = map (dup ((int)a0)); - break; - case 24: // dup3 - ret = map (dup3 ((int)a0, (int)a1, (int)a2)); - break; - case 25: // fcntl - ret = enosys ("fcntl"); - break; - case 29: // ioctl - ret = enosys ("ioctl"); - break; - case 32: // flock - ret = map (flock ((int)a0, (int)a1)); - break; - case 33: // mknodat - ret = map (mknodat ((int)a0, str (a1), (mode_t)a2, (dev_t)a3)); - - case 34: // mkdirat - ret = map (mkdirat ((int)a0, str (a1), (mode_t)a2)); - break; - case 35: // unlinkat - ret = map (unlinkat ((int)a0, str (a1), (int)a2)); - break; - case 36: // symlinkat - ret = map (symlinkat (str (a0), (int)a1, str (a2))); - break; - case 37: // linkat - ret = map (linkat ((int)a0, str (a1), (int)a2, str (a3), (int)a4)); - break; - case 38: // renameat - ret = map (renameat ((int)a0, str (a1), (int)a2, str (a3))); - break; - case 39: // umount - ret = enosys ("umount"); - break; - case 40: // mount - ret = enosys ("mount"); - break; - case 41: // pivot_root - ret = enosys ("pivot_root"); - break; - case 42: // nfsservctl - ret = enosys ("nfsservctl"); - break; - case 43: // statfs - ret = enosys ("statfs"); - break; - case 44: // fstatfs - ret = enosys ("fstatfs"); - break; - case 45: // truncate - ret = map (truncate (str (a0), (off_t)a1)); - break; - break; - case 46: // ftruncate - ret = map (ftruncate ((int)a0, (off_t)a1)); - break; - case 47: // fallocate - ret = enosys ("fallocate"); - break; - case 48: // faccessat - ret = map (faccessat ((int)a0, str (a1), (int)a2, (int)a3)); - break; - case 49: // chdir - ret = map (chdir (str (a0))); - break; - case 50: // fchdir - ret = map (fchdir ((int)a0)); - break; - case 51: // chroot - ret = map (chroot (str (a0))); - break; - case 52: // fchmod - ret = map (fchmod ((int)a0, (mode_t)a1)); - break; - case 53: // fchmodat - ret = map (fchmodat ((int)a0, str (a1), (mode_t)a2, (int)a3)); - break; - case 54: // fchownat - ret = map (fchownat ((int)a0, str (a1), (uid_t)a2, (gid_t)a3, (int)a4)); - break; - case 55: // fchown - ret = map (fchown ((int)a0, (uid_t)a1, (gid_t)a2)); - break; - case 56: // openat - ret = map (openat ((int)a0, str (a1), (int)a2, (int)a3)); - break; - case 57: // close - ret = map (close ((int)a0)); - break; - case 58: // vhangup - ret = enosys ("vhangup"); - break; - case 59: // pipe2 - ret = map (pipe2 (ptr (int, a0), (int)a1)); - break; - case 60: // quotactl - ret = enosys ("quotactl"); - break; - case 61: // getdents64 - ret = enosys ("getdents64"); - break; - case 62: // lseek - ret = map (lseek ((int)a0, (off_t)a1, (int)a2)); - break; - case 63: // read - ret = map (read ((int)a0, ptr (void, a1), (size_t)a2)); - break; - case 64: // write - ret = map (write ((int)a0, ptr (const void, a1), (size_t)a2)); - break; - case 65: // readv - ret = enosys ("readv"); - break; - case 66: // writev - ret = enosys ("writev"); - break; - case 67: // pread - ret = map (pread ((int)a0, ptr (void, a1), (size_t)a2, (off_t)a3)); - break; - case 68: // pwrite - ret = map (pwrite ((int)a0, ptr (const void, a1), (size_t)a2, (off_t)a3)); - break; - case 69: // preadv - ret = enosys ("preadv"); - break; - case 70: // pwritev - ret = enosys ("pwritev"); - break; - case 71: // pwritev - ret = enosys ("sendfile"); - break; - case 72: // pselect6 - ret = enosys ("pselect6"); - break; - case 73: // ppoll - ret = enosys ("ppoll"); - break; - case 74: // signalfd4 - ret = enosys ("signalfd4"); - break; - case 75: // vmsplice - ret = enosys ("vmsplice"); - break; - case 76: // splice - ret = enosys ("splice"); - break; - case 77: // tee - ret = enosys ("tee"); - break; - case 78: // readlinkat - ret = map (readlinkat ((int)a0, str (a1), ptr (char, a2), (size_t)a3)); - break; - case 79: // fstatat - ret = map (fstatat ((int)a0, str (a1), &st, (int)a3)); - stat_to_linux_stat (&lst, &st); - memcpy (ptr (void, a2), &lst, sizeof (lst)); - break; - case 80: // fstat - ret = map (fstat ((int)a0, &st)); - stat_to_linux_stat (&lst, &st); - memcpy (ptr (void, a1), &lst, sizeof (lst)); - break; - case 81: // sync - sync (); - ret = 0; - break; - case 82: // fsync - ret = map (fsync ((int)a0)); - break; - case 83: // fdatasync - ret = map (fdatasync ((int)a0)); - break; - case 84: // sync_file_range - ret = enosys ("sync_file_range"); - break; - case 85: // timerfd_create - ret = enosys ("timerfd_create"); - break; - case 86: // timerfd_settime - ret = enosys ("timerfd_settime"); - break; - case 87: // timerfd_gettime - ret = enosys ("timerfd_gettime"); - break; - case 88: // utimensat - ret = enosys ("utimensat"); - break; - case 89: // acct - ret = acct (str (a0)); - break; - case 90: // capget - ret = enosys ("capget"); - break; - case 91: // capset - ret = enosys ("capset"); - break; - case 92: // personality - ret = enosys ("personality"); - break; - case 93: // exit - exit (a0); - ret = -1; - break; - case 94: // exit_group - ret = enosys ("exit_group"); - break; - case 95: // waitid - ret = enosys ("waitid"); - break; - case 96: // set_tid_address - ret = enosys ("set_tid_address"); - break; - case 97: // unshare - ret = enosys ("unshare"); - break; - case 98: // futex - ret = enosys ("futex"); - break; - case 99: // set_robust_limit - ret = enosys ("set_robust_limit"); - break; - case 100: // get_robust_limit - ret = enosys ("get_robust_limit"); - break; - case 101: // nanosleep - ret = enosys ("nanosleep"); - break; - case 102: // gettimer - ret = enosys ("gettimer"); - break; - case 103: // settimer - ret = enosys ("settimer"); - break; - case 104: // kexec_load - ret = enosys ("kexec_load"); - break; - case 105: // kexec_init_module - ret = enosys ("kexec_init_module"); - break; - case 106: // kexec_delete_module - ret = enosys ("kexec_delete_module"); - break; - case 107: // timer_create - ret = enosys ("timer_create"); - break; - case 108: // timer_gettime - ret = enosys ("timer_gettime"); - break; - case 109: // timer_getoverrun - ret = enosys ("timer_getoverrun"); - break; - case 110: // timer_settime - ret = enosys ("timer_settime"); - break; - case 111: // timer_delete - ret = enosys ("timer_delete"); - break; - case 112: // clock_settime - ret = enosys ("clock_settime"); - break; - case 113: // clock_gettime - ret = enosys ("clock_gettime"); - break; - case 114: // clock_getres - ret = enosys ("clock_getres"); - break; - case 115: // clock_nanosleep - ret = enosys ("clock_nanosleep"); - break; - case 116: // syslog - ret = enosys ("syslog"); - break; - case 117: // ptrace - ret = enosys ("ptrace"); - break; - case 118: // sched_setparam - ret = enosys ("sched_setparam"); - break; - case 119: // sched_setscheduler - ret = enosys ("sched_setscheduler"); - break; - case 120: // sched_getscheduler - ret = enosys ("sched_getscheduler"); - break; - case 121: // sched_getparam - ret = enosys ("sched_getparam"); - break; - case 122: // sched_setaffinity - ret = enosys ("sched_setaffinity"); - break; - case 123: // sched_getaffinity - ret = enosys ("sched_getaffinity"); - break; - case 124: // sched_yield - ret = map (sched_yield ()); - break; - case 125: // sched_get_priority_max - ret = map (sched_get_priority_max ((int)a0)); - break; - case 126: // sched_get_priority_min - ret = map (sched_get_priority_min ((int)a0)); - break; - case 127: // sched_rr_get_interval - ret = enosys ("sched_rr_get_interval"); - break; - case 128: // restart_syscall - ret = enosys ("restart_syscall"); - break; - case 129: // kill - ret = map (kill ((pid_t)a0, (int)a1)); - break; - case 130: // tkill - ret = enosys ("tkill"); - break; - case 131: // tgkill - ret = enosys ("tgkill"); - break; - case 132: // signalstack - ret = enosys ("signalstack"); - break; - case 133: // sigaction - ret = enosys ("sigaction"); - break; - case 134: // sigaction - ret = enosys ("sigaction"); - break; - case 135: // rt_sigprocmask - ret = enosys ("rt_sigprocmask"); - break; - case 136: // sigpending - ret = enosys ("sigpending"); - break; - case 137: // sigtimedwait - ret = enosys ("sigtimedwait"); - break; - case 138: // sigqueueinfo - ret = enosys ("sigqueueinfo"); - break; - case 139: // sigreturn - ret = enosys ("sigreturn"); - break; - case 140: // setpriority - ret = map (setpriority ((int)a0, (id_t)a1, (int)a2)); - break; - case 141: // getpriority - ret = map (getpriority ((int)a0, (id_t)a1)); - break; - case 142: // reboot - ret = enosys ("reboot"); - break; - case 143: // setregid - ret = map (setregid ((gid_t)a0, (gid_t)a1)); - break; - case 144: // setgid - ret = map (setgid ((gid_t)a0)); - break; - case 145: // setreuid - ret = map (setreuid ((uid_t)a0, (uid_t)a1)); - break; - case 146: // setuid - ret = map (setuid ((uid_t)a0)); - break; - case 147: // setresuid - ret = map (setresuid ((uid_t)a0, (uid_t)a1, (uid_t)a2)); - break; - case 148: // getresuid - ret = map (getresuid (ptr (uid_t, a0), ptr (uid_t, a1), ptr (uid_t, a2))); - break; - case 149: // setresgid - ret = map (setresgid ((gid_t)a0, (gid_t)a1, (gid_t)a2)); - break; - case 150: // getresgid - ret = map (getresgid (ptr (gid_t, a0), ptr (gid_t, a1), ptr (gid_t, a2))); - break; - case 151: // setfsuid - ret = enosys ("setfsuid"); - break; - case 152: // setfsgid - ret = enosys ("setfsgid"); - break; - case 153: // times - ret = enosys ("times"); - break; - case 154: // setpgid - ret = map (setpgid ((pid_t)a0, (pid_t)a1)); - break; - case 155: // getpgid - ret = map (getpgid ((pid_t)a0)); - break; - case 156: // getsid - ret = map (getsid ((pid_t)a0)); - break; - case 158: // setsid - ret = map (setsid ()); - break; - case 159: // setgroups - ret = enosys ("setgroups"); - break; - case 160: // uname - ret = map (uname (&un)); - utsname_to_linux_utsname (&lun, &un); - memcpy (ptr (void, a0), &lun, sizeof (lun)); - break; - case 161: // sethostname - ret = enosys ("sethostname"); - break; - case 162: // setdomainname - ret = enosys ("setdomainname"); - break; - case 163: // getrlimit - ret = enosys ("getrlimit"); - break; - case 164: // setrlimit - ret = enosys ("setrlimit"); - break; - case 165: // getrusage - ret = enosys ("getrusage"); - break; - case 166: // umask - ret = map (umask ((mode_t)a0)); - break; - case 167: // prctl - ret = enosys ("prctl"); - break; - case 168: // getcpu - ret = enosys ("getcpu"); - break; - case 169: // gettimeofday - ret = enosys ("gettimeofday"); - break; - case 170: // settimeofday - ret = enosys ("settimeofday"); - break; - case 171: // adjtimex - ret = enosys ("adjtimex"); - break; - case 172: // getpid - ret = map (getpid ()); - break; - case 174: // getuid - ret = map (getuid ()); - break; - case 175: // geteuid - ret = map (geteuid ()); - break; - case 176: // getgid - ret = map (getgid ()); - break; - case 177: // getegid - ret = map (getegid ()); - break; - case 178: // gettid - ret = enosys ("gettid"); - break; - case 179: // sysinfo - ret = enosys ("sysinfo"); - break; - case 180: - case 181: - case 182: - case 183: - case 184: - case 185: - ret = enosys ("mq_*"); - break; - case 186: // msgget - ret = map (msgget ((key_t)a0, (int)a1)); - break; - case 187: // msgctl - ret = enosys ("msgctl"); - break; - case 188: // msgrcv - ret = map (msgrcv ((int)a0, ptr (void, a1), (size_t)a2, (long)a3, (int)a4)); - break; - case 189: // msgsnd - ret = map (msgsnd ((int)a0, ptr (const void, a1), (size_t)a2, (int)a3)); - break; - case 190: // semget - ret = map (semget ((key_t)a0, (int)a1, (int)a2)); - break; - case 191: // semctl - ret = enosys ("semctl"); - break; - case 192: // semtimedop - ret = enosys ("semtimedop"); - break; - case 193: // semop - ret = enosys ("semop"); - break; - case 194: - case 195: - case 196: - case 197: - ret = enosys ("shm*"); - break; - case 198: - case 199: - case 200: - case 201: - case 202: - case 203: - case 204: - case 205: - case 206: - case 207: - case 208: - case 209: - case 210: - case 211: - case 212: - ret = enosys ("socket api"); - break; - case 213: // readahead - ret = enosys ("readahead"); - break; - case 214: // brk - ret = map (my_brk (a0)); - break; - case 215: // munmap - ret = map (munmap (ptr (void, a0), (size_t)a1)); - break; - case 216: // mremap - ret = enosys ("mremap"); - break; - case 217: // add_key - ret = enosys ("add_key"); - break; - case 218: // request_key - ret = enosys ("request_key"); - break; - case 219: // keyctl - ret = enosys ("keyctl"); - break; - case 220: // clone - if (a0 == 17 && a1 == 0) { - // fork - ret = map (fork ()); - } else { - ret = enosys ("clone"); - } - break; - case 221: // execve - ret = map (my_execve (str (a0), a1, a2)); - break; - case 222: // mmap - ptr = mmap (ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5); - if (ptr == NULL) { - ret = -map_errno (errno); - } else if ((size_t)ptr > INT32_MAX) { - ret = -map_errno (EINVAL); - } else { - ret = (size_t)ptr; - } - break; - case 223: // fadvise64 - ret = enosys ("fadvise64"); - break; - case 224: // swapon - ret = enosys ("swapon"); - break; - case 225: // swapoff - ret = enosys ("swapoff"); - break; - case 226: // mprotect - ret = map (mprotect (ptr (void, a0), (size_t)a1, (int)a2)); - break; - case 227: // msync - ret = map (msync (ptr (void, a0), (size_t)a1, (int)a2)); - break; - case 228: // mlock - ret = map (mlock (ptr (void, a0), (size_t)a1)); - break; - case 229: // munlock - ret = map (munlock (ptr (void, a0), (size_t)a1)); - break; - case 230: // mlockall - ret = map (mlockall ((int)a0)); - break; - case 231: // munlockall - ret = map (munlockall ()); - break; - case 232: // mincore - ret = enosys ("mincore"); - break; - case 233: // madvise - ret = map (madvise (ptr (void, a0), (size_t)a1, (int)a2)); - break; - case 234: // remap_file_pages - ret = enosys ("remap_file_pages"); - break; - case 235: // mbind - ret = enosys ("mbind"); - break; - case 236: // get_mempolicy - ret = enosys ("get_mempolicy"); - break; - case 237: // set_mempolicy - ret = enosys ("set_mempolicy"); - break; - case 238: // migrate_pages - ret = enosys ("migrate_pages"); - break; - case 239: // move_pages - ret = enosys ("move_pages"); - break; - case 240: // rt_tgsigqueueinfo - ret = enosys ("rt_tgsigqueueinfo"); - break; - case 241: // perf_event_open - ret = enosys ("perf_event_open"); - break; - case 242: // accept4 - ret = enosys ("accept4"); - break; - case 243: // recvmsg - ret = enosys ("recvmsg"); - break; - case 244: - case 245: - case 246: - case 247: - case 248: - case 249: - case 250: - case 251: - case 252: - case 253: - case 254: - case 255: - case 256: - case 257: - case 258: - case 259: - ret = enosys ("arch-specific"); - break; - case 260: - ret = enosys ("wait4"); - break; - case 261: // prlimit64 - ret = enosys ("prlimit64"); - break; - case 262: // fanotify_init - ret = enosys ("fanotify_init"); - break; - case 263: // fanotify_mark - ret = enosys ("fanotify_mark"); - break; - case 264: // name_to_handle_at - ret = enosys ("name_to_handle_at"); - break; - case 265: // open_by_handle_at - ret = enosys ("open_by_handle_at"); - break; - case 266: // clock_adjtime - ret = enosys ("clock_adjtime"); - break; - case 267: // syncfs - ret = enosys ("syncfs"); - break; - case 268: // setns - ret = enosys ("setns"); - break; - case 269: // sendmsg - ret = enosys ("sendmsg"); - break; - case 270: // process_vm_readv - ret = enosys ("process_vm_readv"); - break; - case 271: // process_vm_writev - ret = enosys ("process_vm_writev"); - break; - case 272: // kcmp - ret = enosys ("kcmp"); - break; - case 273: // finit_module - ret = enosys ("finit_module"); - break; - case 274: // sched_setattr - ret = enosys ("sched_setattr"); - break; - case 275: // sched_getattr - ret = enosys ("sched_getattr"); - break; - case 276: // renameat2 - ret = enosys ("renameat2"); - break; - case 277: // seccomp - ret = enosys ("seccomp"); - break; - case 278: // getrandom - ret = enosys ("getrandom"); - break; - case 279: // memfd_create - ret = enosys ("seccomp"); - break; - case 280: // bpf - ret = enosys ("bpf"); - break; - case 281: // execveat - ret = enosys ("execveat"); - break; - case 282: // userfaultfd - ret = enosys ("usefaultfd"); - break; - case 283: // membarrier - ret = enosys ("membarrier"); - break; - case 284: // mlock2 - ret = enosys ("mlock2"); - break; - case 285: // copy_file_range - ret = enosys ("copy_file_range"); - break; - case 286: // preadv2 - ret = enosys ("preadv2"); - break; - case 287: // pwritev2 - ret = enosys ("pwritev2"); - break; - case 288: // pkey_mprotect - ret = enosys ("pkey_mprotect"); - break; - case 289: // pkey_alloc - ret = enosys ("pkey_alloc"); - break; - case 290: // pkey_free - ret = enosys ("pkey_free"); - break; - case 291: // statx - ret = enosys ("statx"); - break; - case 292: // io_pgetevents - ret = enosys ("io_pgetevents"); - break; - case 293: // rseq - ret = enosys ("rseq"); - break; - case 294: // kexec_file_load - ret = enosys ("kexec_file_load"); - break; - case 1024: // open - ret = map (open ((const char *)(size_t)a0, (int)a1, (int)a2)); - break; - case 1025: // link - ret = map (link (str (a0), str (a1))); - break; - case 1026: // unlink - ret = map (unlink (str (a0))); - break; - case 1030: // mkdir - ret = map (mkdir (str (a0), (mode_t)a1)); - break; - case 1033: // access - ret = map (access (str (a0), (int)a1)); - break; - case 1038: // stat - ret = map (stat (str (a0), &st)); - stat_to_linux_stat (&lst, &st); - memcpy (ptr (void, a1), &lst, sizeof (lst)); - break; - case 1039: // lstat - ret = map (lstat (str (a0), &st)); - stat_to_linux_stat (&lst, &st); - memcpy (ptr (void, a1), &lst, sizeof (lst)); - break; - case 1062: // time - ret = enosys ("time"); - break; - case 2011: // getmainvars - ret = enosys ("getmainvars"); - break; - case 2048: - fprintf (stderr, "DEBUG: %u\n", a0); - ret = 0; - break; - default: - warnx ("%08x: unimplemented syscall %u", pc - 4, a7); - ret = -map_errno (ENOSYS); - break; - } - cpu_set (10, ret); -} - blob - 5df22c2c59aad064533fec3b092b5bd3b62773b7 blob + f107b56f5fe7a8f694784c2a8903a7c54f1e5c14 --- syscalls.inc +++ syscalls.inc @@ -42,7 +42,7 @@ .set SYS_pwrite, 68 .set SYS_preadv, 69 .set SYS_pwritev, 70 -.set SYS_pwritev, 71 +.set SYS_sendfile, 71 .set SYS_pselect6, 72 .set SYS_ppoll, 73 .set SYS_signalfd4, 74 @@ -104,7 +104,7 @@ .set SYS_tkill, 130 .set SYS_tgkill, 131 .set SYS_signalstack, 132 -.set SYS_sigaction, 133 +.set SYS_sigsuspend, 133 .set SYS_sigaction, 134 .set SYS_rt_sigprocmask, 135 .set SYS_sigpending, 136 @@ -231,3 +231,4 @@ .set SYS_lstat, 1039 .set SYS_time, 1062 .set SYS_getmainvars, 2011 +.set SYS_debug, 2048 blob - e2cf2fffaab6a3f386b08769438e3f48c8d37b19 blob + 85a84552dd1982a85a006dc9c3b5193fa5b25c11 --- test.S +++ test.S @@ -6,11 +6,11 @@ child: .string "Child\n" arg0: path: .string "./hello.elf" argv: - .int arg0 - .int 0 + .dword arg0 + .dword 0 envp: - .int 0 + .dword 0 .section .text .global _start @@ -50,17 +50,16 @@ _start: li a7, SYS_write ecall - li a0, 0 li a7, SYS_exit ecall -# printhex(u32 a0) +# printhex(u64 a0) printhex: addi sp, sp, -12 sw s0, 8(sp) sw s1, 4(sp) - li s0, 28 + li s0, 52 mv s1, a0 .Loop: