yeah
This commit is contained in:
+3
-5
@@ -1,8 +1,6 @@
|
||||
#include <zinnia/archctl.h>
|
||||
#include <zinnia/syscalls.h>
|
||||
#include <zinnia/syscall.h>
|
||||
|
||||
errno_t arch_archctl(zn_archctl_t op, uintptr_t value);
|
||||
|
||||
errno_t syscall_archctl(struct arch_context* ctx) {
|
||||
return arch_archctl((zn_archctl_t)ctx->ARCH_CTX_A0, (uintptr_t)ctx->ARCH_CTX_A1);
|
||||
void syscall_archctl(struct arch_context* ctx) {
|
||||
ctx->ARCH_CTX_RET0 = arch_archctl(ctx->ARCH_CTX_A0, ctx->ARCH_CTX_A1);
|
||||
}
|
||||
|
||||
+148
-7
@@ -6,20 +6,161 @@
|
||||
#include <zinnia/types.h>
|
||||
#include <zinnia/utils.h>
|
||||
|
||||
static const syscall_fn_t dispatch_table[] = {
|
||||
#undef __ZINNIA_UAPI_SYSCALL_NUMBERS_H // We want to include the header again
|
||||
#define __SYSCALL_DEFINE(idx, name) [idx] = syscall_##name,
|
||||
#include <uapi/syscall_numbers.h>
|
||||
#undef __SYSCALL_DEFINE
|
||||
const struct syscall syscall_table[256] = {
|
||||
[0] = {sys_exit, 0},
|
||||
[1] = {sys_syslog, 0},
|
||||
[2] = {sys_getuname, 0},
|
||||
[3] = {sys_setuname, 0},
|
||||
[4] = {sys_archctl, 0},
|
||||
[5] = {sys_reboot, 0},
|
||||
[6] = {sys_mmap, 0},
|
||||
[7] = {sys_munmap, 0},
|
||||
[8] = {sys_mprotect, 0},
|
||||
[9] = {sys_madvise, 0},
|
||||
[10] = {sys_sigprocmask, 0},
|
||||
[11] = {sys_sigsuspend, 0},
|
||||
[12] = {sys_sigpending, 0},
|
||||
[13] = {sys_sigaction, 0},
|
||||
[14] = {sys_sigtimedwait, 0},
|
||||
[15] = {sys_sigaltstack, 0},
|
||||
[16] = {sys_sigreturn, 0},
|
||||
[17] = {sys_sigqueue, 0},
|
||||
[18] = {sys_execve, 0},
|
||||
[19] = {sys_fexecve, 0},
|
||||
[20] = {sys_fork, SYSKIND_CONTEXT},
|
||||
[21] = {sys_kill, 0},
|
||||
[22] = {sys_gettid, 0},
|
||||
[23] = {sys_getpid, 0},
|
||||
[24] = {sys_getppid, 0},
|
||||
[25] = {sys_waitid, 0},
|
||||
[26] = {sys_waitpid, 0},
|
||||
[27] = {sys_pread, 0},
|
||||
[28] = {sys_readv, 0},
|
||||
[29] = {sys_pwrite, 0},
|
||||
[30] = {sys_writev, 0},
|
||||
[31] = {sys_seek, 0},
|
||||
[32] = {sys_ioctl, 0},
|
||||
[33] = {sys_openat, 0},
|
||||
[34] = {sys_close, 0},
|
||||
[35] = {sys_fstat, 0},
|
||||
[36] = {sys_fstatat, 0},
|
||||
[37] = {sys_statvfs, 0},
|
||||
[38] = {sys_fstatvfs, 0},
|
||||
[39] = {sys_faccessat, 0},
|
||||
[40] = {sys_fcntl, 0},
|
||||
[41] = {sys_ftruncate, 0},
|
||||
[42] = {sys_truncate, 0},
|
||||
[43] = {sys_fallocate, 0},
|
||||
[44] = {sys_fadvise, 0},
|
||||
[45] = {sys_utimensat, 0},
|
||||
[46] = {sys_mknodat, 0},
|
||||
[47] = {sys_getcwd, 0},
|
||||
[48] = {sys_chdir, 0},
|
||||
[49] = {sys_fchdir, 0},
|
||||
[50] = {sys_mkdirat, 0},
|
||||
[51] = {sys_rmdirat, 0},
|
||||
[52] = {sys_getdents, 0},
|
||||
[53] = {sys_renameat, 0},
|
||||
[54] = {sys_fchmod, 0},
|
||||
[55] = {sys_fchmodat, 0},
|
||||
[56] = {sys_fchownat, 0},
|
||||
[57] = {sys_linkat, 0},
|
||||
[58] = {sys_symlinkat, 0},
|
||||
[59] = {sys_unlinkat, 0},
|
||||
[60] = {sys_readlinkat, 0},
|
||||
[61] = {sys_flock, 0},
|
||||
[62] = {sys_ppoll, 0},
|
||||
[63] = {sys_dup, 0},
|
||||
[64] = {sys_dup3, 0},
|
||||
[65] = {sys_sync, 0},
|
||||
[66] = {sys_fsync, 0},
|
||||
[67] = {sys_fdatasync, 0},
|
||||
[68] = {sys_getgroups, 0},
|
||||
[69] = {sys_setgroups, 0},
|
||||
[70] = {sys_getsid, 0},
|
||||
[71] = {sys_setsid, 0},
|
||||
[72] = {sys_setuid, 0},
|
||||
[73] = {sys_getuid, 0},
|
||||
[74] = {sys_setgid, 0},
|
||||
[75] = {sys_getgid, 0},
|
||||
[76] = {sys_geteuid, 0},
|
||||
[77] = {sys_seteuid, 0},
|
||||
[78] = {sys_getegid, 0},
|
||||
[79] = {sys_setegid, 0},
|
||||
[80] = {sys_getpgid, 0},
|
||||
[81] = {sys_setpgid, 0},
|
||||
[82] = {sys_getresuid, 0},
|
||||
[83] = {sys_setresuid, 0},
|
||||
[84] = {sys_getresgid, 0},
|
||||
[85] = {sys_setresgid, 0},
|
||||
[86] = {sys_setreuid, 0},
|
||||
[87] = {sys_setregid, 0},
|
||||
[88] = {sys_umask, 0},
|
||||
[89] = {sys_pipe, 0},
|
||||
[90] = {sys_futex_wait, 0},
|
||||
[91] = {sys_futex_wake, 0},
|
||||
[92] = {sys_thread_create, 0},
|
||||
[93] = {sys_thread_kill, 0},
|
||||
[94] = {sys_thread_exit, 0},
|
||||
[95] = {sys_thread_setname, 0},
|
||||
[96] = {sys_thread_getname, 0},
|
||||
[97] = {sys_timer_create, 0},
|
||||
[98] = {sys_timer_set, 0},
|
||||
[99] = {sys_timer_get, 0},
|
||||
[100] = {sys_timer_getoverrun, 0},
|
||||
[101] = {sys_timer_delete, 0},
|
||||
[102] = {sys_itimer_get, 0},
|
||||
[103] = {sys_itimer_set, 0},
|
||||
[104] = {sys_clock_get, 0},
|
||||
[105] = {sys_clock_getres, 0},
|
||||
[106] = {sys_clock_set, 0},
|
||||
[107] = {sys_sleep, 0},
|
||||
[108] = {sys_yield, 0},
|
||||
[109] = {sys_chroot, 0},
|
||||
[110] = {sys_mount, 0},
|
||||
[111] = {sys_umount, 0},
|
||||
[112] = {sys_socket, 0},
|
||||
[113] = {sys_socketpair, 0},
|
||||
[114] = {sys_shutdown, 0},
|
||||
[115] = {sys_bind, 0},
|
||||
[116] = {sys_connect, 0},
|
||||
[117] = {sys_accept, 0},
|
||||
[118] = {sys_listen, 0},
|
||||
[119] = {sys_getpeername, 0},
|
||||
[120] = {sys_getsockname, 0},
|
||||
[121] = {sys_getsockopt, 0},
|
||||
[122] = {sys_setsockopt, 0},
|
||||
[123] = {sys_sendmsg, 0},
|
||||
[124] = {sys_recvmsg, 0},
|
||||
[125] = {sys_getentropy, 0},
|
||||
[126] = {sys_getrusage, 0},
|
||||
[127] = {sys_getrlimit, 0},
|
||||
[128] = {sys_setrlimit, 0},
|
||||
[129] = {sys_getpriority, 0},
|
||||
[130] = {sys_setpriority, 0},
|
||||
[131] = {sys_sched_getparam, 0},
|
||||
[132] = {sys_sched_setparam, 0},
|
||||
[133] = {sys_module_insert, 0},
|
||||
[134] = {sys_module_remove, 0},
|
||||
[135] = {sys_epoll_create, 0},
|
||||
[136] = {sys_epoll_ctl, 0},
|
||||
[137] = {sys_epoll_pwait, 0},
|
||||
[138] = {sys_timerfd_create, 0},
|
||||
[139] = {sys_timerfd_gettime, 0},
|
||||
[140] = {sys_timerfd_settime, 0},
|
||||
[141] = {sys_signalfd_create, 0},
|
||||
[142] = {sys_eventfd_create, 0},
|
||||
[143] = {sys_msync, 0},
|
||||
[144] = {sys_sysconf, 0},
|
||||
};
|
||||
|
||||
void syscall_dispatch(struct arch_context* ctx) {
|
||||
const size_t num = ctx->ARCH_CTX_NUM;
|
||||
|
||||
if (num >= ARRAY_SIZE(dispatch_table)) {
|
||||
if (num >= ARRAY_SIZE(syscall_table) || syscall_table[num].handler == nullptr) {
|
||||
ctx->ARCH_CTX_RET0 = ENOSYS;
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_table[num](ctx);
|
||||
syscall_table[num].handler(ctx);
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/handle.h>
|
||||
#include <zinnia/namespace.h>
|
||||
#include <zinnia/percpu.h>
|
||||
#include <zinnia/rights.h>
|
||||
#include <zinnia/syscalls.h>
|
||||
#include <zinnia/usercopy.h>
|
||||
|
||||
errno_t syscall_handle_clone(struct arch_context* ctx) {
|
||||
zn_handle_t handle = ctx->ARCH_CTX_A0;
|
||||
zn_rights_t cloned_rights = ctx->ARCH_CTX_A1;
|
||||
__user zn_handle_t* cloned = (__user zn_handle_t*)ctx->ARCH_CTX_A2;
|
||||
|
||||
struct task* current = percpu_get()->sched.current;
|
||||
struct namespace* ns = current->namespace;
|
||||
|
||||
struct namespace_desc desc;
|
||||
errno_t status = namespace_get(ns, handle, &desc);
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
zn_handle_t new_handle;
|
||||
status = namespace_clone_desc(ns, &desc, cloned_rights, &new_handle);
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
if (!usercopy_write(cloned, &new_handle, sizeof(new_handle))) {
|
||||
namespace_del_desc(ns, new_handle);
|
||||
return ZN_ERR_BAD_BUFFER;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
errno_t syscall_handle_drop(struct arch_context* ctx) {
|
||||
zn_handle_t handle = ctx->ARCH_CTX_A0;
|
||||
struct task* current = percpu_get()->sched.current;
|
||||
|
||||
return namespace_del_desc(current->namespace, handle);
|
||||
}
|
||||
|
||||
errno_t syscall_handle_validate(struct arch_context* ctx) {
|
||||
zn_handle_t handle = ctx->ARCH_CTX_A0;
|
||||
struct task* current = percpu_get()->sched.current;
|
||||
|
||||
struct namespace_desc desc;
|
||||
return namespace_get(current->namespace, handle, &desc);
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
kernel_sources += files(
|
||||
'archctl.c',
|
||||
'dispatch.c',
|
||||
'futex.c',
|
||||
)
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/syscalls.h>
|
||||
|
||||
errno_t syscall_random_entropy(struct arch_context* ctx) {
|
||||
return ZN_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
errno_t syscall_random_get(struct arch_context* ctx) {
|
||||
return ZN_ERR_UNSUPPORTED;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#include <zinnia/alloc.h>
|
||||
#include <zinnia/clock.h>
|
||||
#include <zinnia/console.h>
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/syscalls.h>
|
||||
#include <zinnia/usercopy.h>
|
||||
|
||||
errno_t syscall_log(struct arch_context* ctx) {
|
||||
__user const char* msg = (__user const char*)ctx->ARCH_CTX_A0;
|
||||
size_t len = ctx->ARCH_CTX_A1;
|
||||
|
||||
char* buf = mem_alloc(len, ALLOC_NOZERO);
|
||||
if (!buf) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (usercopy_read(buf, msg, len)) {
|
||||
console_write(buf, len);
|
||||
|
||||
mem_free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mem_free(buf);
|
||||
return ZN_ERR_BAD_BUFFER;
|
||||
}
|
||||
|
||||
errno_t syscall_page_size(struct arch_context* ctx) {
|
||||
__user size_t* out = (__user size_t*)ctx->ARCH_CTX_A0;
|
||||
|
||||
size_t size = arch_mem_page_size();
|
||||
if (!usercopy_write(out, &size, sizeof(size)))
|
||||
return ZN_ERR_BAD_BUFFER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
errno_t syscall_time(struct arch_context* ctx) {
|
||||
__user uint64_t* out = (__user uint64_t*)ctx->ARCH_CTX_A0;
|
||||
|
||||
uint64_t time = clock_get_elapsed_ns();
|
||||
if (!usercopy_write(out, &time, sizeof(time)))
|
||||
return ZN_ERR_BAD_BUFFER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <zinnia/alloc.h>
|
||||
#include <zinnia/compiler.h>
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/handle.h>
|
||||
#include <zinnia/percpu.h>
|
||||
#include <zinnia/print.h>
|
||||
#include <zinnia/sched.h>
|
||||
#include <zinnia/syscall.h>
|
||||
#include <zinnia/usercopy.h>
|
||||
|
||||
errno_t syscall_thread_create(struct arch_context* ctx) {
|
||||
zn_handle_t ns_handle = ctx->ARCH_CTX_A0;
|
||||
__user const char* name = (__user const char*)ctx->ARCH_CTX_A1;
|
||||
size_t name_len = ctx->ARCH_CTX_A2;
|
||||
enum zn_thread_flags flags = ctx->ARCH_CTX_A3;
|
||||
__user zn_handle_t* out = (__user zn_handle_t*)ctx->ARCH_CTX_A4;
|
||||
|
||||
struct task* current = percpu_get()->sched.current;
|
||||
// Resolve namespace.
|
||||
struct namespace* ns;
|
||||
if (ns_handle == ZN_HANDLE_THIS_NS) {
|
||||
ns = current->namespace;
|
||||
} else {
|
||||
struct namespace_desc ns_desc;
|
||||
errno_t status = namespace_get(current->namespace, ns_handle, &ns_desc);
|
||||
if (status != 0)
|
||||
return status;
|
||||
if (ns_desc.type != NAMESPACE_DESC_NS)
|
||||
return ZN_ERR_BAD_HANDLE;
|
||||
ns = ns_desc.value.namespace;
|
||||
}
|
||||
|
||||
// Copy name from userspace.
|
||||
if (name_len == 0 || name_len >= TASK_NAME_MAX)
|
||||
return EINVAL;
|
||||
|
||||
char task_name[TASK_NAME_MAX] = {};
|
||||
if (!usercopy_read(task_name, name, name_len))
|
||||
return ZN_ERR_BAD_BUFFER;
|
||||
|
||||
// Create the task sharing the caller's address space.
|
||||
// Uses sched_to_user as a placeholder entry — the real IP/SP come from thread_start.
|
||||
struct task* new_task;
|
||||
errno_t status = task_create(task_name, current->space, ns, sched_to_user, 0, &new_task);
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
// Register the task as a handle in the caller's namespace.
|
||||
struct namespace_desc desc = {
|
||||
.type = NAMESPACE_DESC_TASK,
|
||||
.rights = ZN_RIGHTS_ALL,
|
||||
.value.task = new_task,
|
||||
};
|
||||
|
||||
zn_handle_t handle;
|
||||
status = namespace_add_desc(current->namespace, desc, &handle);
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
if (!usercopy_write(out, &handle, sizeof(handle))) {
|
||||
namespace_del_desc(current->namespace, handle);
|
||||
return ZN_ERR_BAD_BUFFER;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
errno_t syscall_thread_start(struct arch_context* ctx) {
|
||||
zn_handle_t thread_handle = ctx->ARCH_CTX_A0;
|
||||
uintptr_t ip = ctx->ARCH_CTX_A1;
|
||||
uintptr_t sp = ctx->ARCH_CTX_A2;
|
||||
uintptr_t arg = ctx->ARCH_CTX_A3;
|
||||
|
||||
struct task* current = percpu_get()->sched.current;
|
||||
struct sched_percpu* sched = &percpu_get()->sched;
|
||||
|
||||
// Look up the task.
|
||||
struct namespace_desc desc;
|
||||
errno_t status = namespace_get(current->namespace, thread_handle, &desc);
|
||||
if (status != 0)
|
||||
return status;
|
||||
if (desc.type != NAMESPACE_DESC_TASK)
|
||||
return ZN_ERR_BAD_HANDLE;
|
||||
|
||||
struct task* task = desc.value.task;
|
||||
|
||||
// Allocate a start info block for the thread entry.
|
||||
struct task_start_info* info = mem_alloc(sizeof(struct task_start_info), 0);
|
||||
if (!info)
|
||||
return ENOMEM;
|
||||
|
||||
info->ip = ip;
|
||||
info->sp = sp;
|
||||
info->arg = arg;
|
||||
|
||||
// Re-initialize the task's arch context to enter user mode via sched_to_user_arg.
|
||||
status =
|
||||
arch_task_init(&task->context, sched_to_user, (uintptr_t)info, task->kernel_stack + KERNEL_STACK_SIZE, true);
|
||||
if (status != 0) {
|
||||
mem_free(info);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Add to run queue.
|
||||
sched_add_task(sched, task);
|
||||
return 0;
|
||||
}
|
||||
|
||||
errno_t syscall_thread_exit(struct arch_context* ctx) {
|
||||
struct sched_percpu* sched = &percpu_get()->sched;
|
||||
sched->current->state = TASK_STATE_DEAD;
|
||||
sched_yield(sched);
|
||||
unreachable();
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/syscalls.h>
|
||||
|
||||
errno_t syscall_vas_create(struct arch_context* ctx) {
|
||||
return ZN_ERR_UNSUPPORTED;
|
||||
}
|
||||
Reference in New Issue
Block a user