#include #include "user/syscall.h" #include "user/errno.h" #include "user/time.h" #include "sys/sched.h" #include "arch/amd64/cpu.h" #include "sys/thread.h" #include "sys/debug.h" #include "sys/mem/shmem.h" #include "sys/sys_file.h" #include "sys/sys_sys.h" #include "sys/sys_proc.h" #if defined(ENABLE_NET) #include "sys/sys_net.h" #endif #include "sys/mod.h" #define MSR_IA32_STAR 0xC0000081 #define MSR_IA32_LSTAR 0xC0000082 #define MSR_IA32_SFMASK 0xC0000084 extern void syscall_entry(void); static void sys_debug_trace(const char *msg, size_t lim) { struct thread *thr = thread_self; _assert(thr); struct process *proc = thr->proc; _assert(proc); for (size_t i = 0; i < lim && msg[i]; ++i) { debugc(DEBUG_DEFAULT, msg[i]); } } static int sys_debug_instr(uint32_t cmd, void *arg0, void *arg1, void *arg2) { struct thread *thr = thread_self; _assert(thr); struct process *proc = thr->proc; _assert(proc); asm volatile ("cli"); switch (cmd) { case 1: // YGG_INSTR_MAP_GET { uintptr_t res = mm_map_get(proc->space, (uintptr_t) arg0, arg2); if (res == MM_NADDR) { return -ENOENT; } if (arg1) { *((uintptr_t *) arg1) = res; } } return 0; default: panic("Invalid instrumentation syscall: %u\n", cmd); } } void *syscall_table[256] = { // I/O [SYSCALL_NR_READ] = sys_read, [SYSCALL_NR_WRITE] = sys_write, [SYSCALL_NR_OPENAT] = sys_openat, [SYSCALL_NR_CLOSE] = sys_close, [SYSCALL_NR_FSTATAT] = sys_fstatat, [SYSCALL_NR_LSEEK] = sys_lseek, [SYSCALL_NR_MMAP] = sys_mmap, [SYSCALL_NR_MUNMAP] = sys_munmap, [SYSCALL_NR_IOCTL] = sys_ioctl, [SYSCALL_NR_FACCESSAT] = sys_faccessat, [SYSCALL_NR_PIPE] = sys_pipe, [SYSCALL_NR_SELECT] = sys_select, [SYSCALL_NR_DUP] = sys_dup, [SYSCALL_NR_DUP2] = sys_dup2, [SYSCALL_NR_TRUNCATE] = sys_truncate, [SYSCALL_NR_FTRUNCATE] = sys_ftruncate, [SYSCALL_NR_GETCWD] = sys_getcwd, [SYSCALL_NR_CHDIR] = sys_chdir, [SYSCALL_NR_MKDIRAT] = sys_mkdirat, [SYSCALL_NR_CREAT] = sys_creat, [SYSCALL_NR_UNLINKAT] = sys_unlinkat, [SYSCALL_NR_READDIR] = sys_readdir, [SYSCALL_NR_CHMOD] = sys_chmod, [SYSCALL_NR_READLINKAT] = sys_readlinkat, [SYSCALL_NR_CHOWN] = sys_chown, [SYSCALL_NR_MKNOD] = sys_mknod, // User control [SYSCALL_NR_GETUID] = sys_getuid, [SYSCALL_NR_GETGID] = sys_getgid, [SYSCALL_NR_SETUID] = sys_setuid, [SYSCALL_NR_SETGID] = sys_setgid, // Process control [SYSCALL_NRX_SIGENTRY] = sys_sigentry, [SYSCALL_NR_EXECVE] = sys_execve, [SYSCALL_NR_YIELD] = sys_yield, [SYSCALL_NR_GETPID] = sys_getpid, [SYSCALL_NR_CLONE] = sys_clone, [SYSCALL_NR_KILL] = sys_kill, [SYSCALL_NR_EXIT] = sys_exit, [SYSCALL_NR_SIGRETURN] = sys_sigreturn, [SYSCALL_NRX_WAITPID] = sys_waitpid, [SYSCALL_NR_GETPGID] = sys_getpgid, [SYSCALL_NR_SETPGID] = sys_setpgid, [SYSCALL_NR_SETSID] = sys_setsid, [SYSCALL_NR_SIGALTSTACK] = sys_sigaltstack, [SYSCALL_NR_GETPPID] = sys_getppid, // Shared memory [SYSCALL_NR_SHMGET] = sys_shmget, [SYSCALL_NR_SHMAT] = sys_shmat, // System [SYSCALL_NR_SYNC] = sys_sync, [SYSCALL_NR_MOUNT] = sys_mount, [SYSCALL_NRX_UMOUNT] = sys_umount, [SYSCALL_NR_UNAME] = sys_uname, [SYSCALL_NR_NANOSLEEP] = sys_nanosleep, [SYSCALL_NR_GETTIMEOFDAY] = sys_gettimeofday, [SYSCALL_NR_REBOOT] = sys_reboot, [SYSCALL_NRX_MODULE_LOAD] = sys_module_load, [SYSCALL_NRX_MODULE_UNLOAD] = sys_module_unload, #if defined(ENABLE_NET) // Network [SYSCALL_NR_SOCKET] = sys_socket, [SYSCALL_NR_CONNECT] = sys_connect, [SYSCALL_NR_ACCEPT] = sys_accept, [SYSCALL_NR_SENDTO] = sys_sendto, [SYSCALL_NR_RECVFROM] = sys_recvfrom, [SYSCALL_NR_BIND] = sys_bind, [SYSCALL_NR_SETSOCKOPT] = sys_setsockopt, [SYSCALL_NRX_NETCTL] = sys_netctl, #endif // Extension [SYSCALL_NRX_TRACE] = sys_debug_trace, [SYSCALL_NRX_INSTR] = sys_debug_instr, }; int syscall_undefined(uint64_t rax) { debugs(DEBUG_DEFAULT, "\033[41m"); if (sched_ready) { thread_dump(DEBUG_DEFAULT, thread_self); } debugf(DEBUG_DEFAULT, "Undefined system call: %d\n", rax); debugs(DEBUG_DEFAULT, "\033[0m"); thread_signal(thread_self, SIGSYS); // TODO: more context? return -ENOSYS; } void syscall_init(void) { // LSTAR = syscall_entry wrmsr(MSR_IA32_LSTAR, (uintptr_t) syscall_entry); // SFMASK = (1 << 9) /* IF */ wrmsr(MSR_IA32_SFMASK, (1 << 9)); // STAR = ((ss3 - 8) << 48) | (cs0 << 32) wrmsr(MSR_IA32_STAR, ((uint64_t) (0x1B - 8) << 48) | ((uint64_t) 0x08 << 32)); // Set SCE bit uint64_t efer = rdmsr(MSR_IA32_EFER); efer |= (1 << 0); wrmsr(MSR_IA32_EFER, efer); }