171 lines
5.5 KiB
C
171 lines
5.5 KiB
C
#include <config.h>
|
|
|
|
#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);
|
|
}
|