Restructured and rewritten entire codebase

This commit is contained in:
Alex
2023-10-09 01:16:24 +03:00
parent 446a571018
commit 889e1522a3
484 changed files with 15683 additions and 14032 deletions

1155
syscalls/linux.cpp Normal file

File diff suppressed because it is too large Load Diff

0
syscalls/linux/.gitkeep Normal file
View File

381
syscalls/linux_syscalls.hpp Normal file
View File

@ -0,0 +1,381 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_LINUX_SYSCALLS_H__
#define __FENNIX_KERNEL_LINUX_SYSCALLS_H__
#include <types.h>
#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4
#define __NR_fstat 5
#define __NR_lstat 6
#define __NR_poll 7
#define __NR_lseek 8
#define __NR_mmap 9
#define __NR_mprotect 10
#define __NR_munmap 11
#define __NR_brk 12
#define __NR_rt_sigaction 13
#define __NR_rt_sigprocmask 14
#define __NR_rt_sigreturn 15
#define __NR_ioctl 16
#define __NR_pread64 17
#define __NR_pwrite64 18
#define __NR_readv 19
#define __NR_writev 20
#define __NR_access 21
#define __NR_pipe 22
#define __NR_select 23
#define __NR_sched_yield 24
#define __NR_mremap 25
#define __NR_msync 26
#define __NR_mincore 27
#define __NR_madvise 28
#define __NR_shmget 29
#define __NR_shmat 30
#define __NR_shmctl 31
#define __NR_dup 32
#define __NR_dup2 33
#define __NR_pause 34
#define __NR_nanosleep 35
#define __NR_getitimer 36
#define __NR_alarm 37
#define __NR_setitimer 38
#define __NR_getpid 39
#define __NR_sendfile 40
#define __NR_socket 41
#define __NR_connect 42
#define __NR_accept 43
#define __NR_sendto 44
#define __NR_recvfrom 45
#define __NR_sendmsg 46
#define __NR_recvmsg 47
#define __NR_shutdown 48
#define __NR_bind 49
#define __NR_listen 50
#define __NR_getsockname 51
#define __NR_getpeername 52
#define __NR_socketpair 53
#define __NR_setsockopt 54
#define __NR_getsockopt 55
#define __NR_clone 56
#define __NR_fork 57
#define __NR_vfork 58
#define __NR_execve 59
#define __NR_exit 60
#define __NR_wait4 61
#define __NR_kill 62
#define __NR_uname 63
#define __NR_semget 64
#define __NR_semop 65
#define __NR_semctl 66
#define __NR_shmdt 67
#define __NR_msgget 68
#define __NR_msgsnd 69
#define __NR_msgrcv 70
#define __NR_msgctl 71
#define __NR_fcntl 72
#define __NR_flock 73
#define __NR_fsync 74
#define __NR_fdatasync 75
#define __NR_truncate 76
#define __NR_ftruncate 77
#define __NR_getdents 78
#define __NR_getcwd 79
#define __NR_chdir 80
#define __NR_fchdir 81
#define __NR_rename 82
#define __NR_mkdir 83
#define __NR_rmdir 84
#define __NR_creat 85
#define __NR_link 86
#define __NR_unlink 87
#define __NR_symlink 88
#define __NR_readlink 89
#define __NR_chmod 90
#define __NR_fchmod 91
#define __NR_chown 92
#define __NR_fchown 93
#define __NR_lchown 94
#define __NR_umask 95
#define __NR_gettimeofday 96
#define __NR_getrlimit 97
#define __NR_getrusage 98
#define __NR_sysinfo 99
#define __NR_times 100
#define __NR_ptrace 101
#define __NR_getuid 102
#define __NR_syslog 103
#define __NR_getgid 104
#define __NR_setuid 105
#define __NR_setgid 106
#define __NR_geteuid 107
#define __NR_getegid 108
#define __NR_setpgid 109
#define __NR_getppid 110
#define __NR_getpgrp 111
#define __NR_setsid 112
#define __NR_setreuid 113
#define __NR_setregid 114
#define __NR_getgroups 115
#define __NR_setgroups 116
#define __NR_setresuid 117
#define __NR_getresuid 118
#define __NR_setresgid 119
#define __NR_getresgid 120
#define __NR_getpgid 121
#define __NR_setfsuid 122
#define __NR_setfsgid 123
#define __NR_getsid 124
#define __NR_capget 125
#define __NR_capset 126
#define __NR_rt_sigpending 127
#define __NR_rt_sigtimedwait 128
#define __NR_rt_sigqueueinfo 129
#define __NR_rt_sigsuspend 130
#define __NR_sigaltstack 131
#define __NR_utime 132
#define __NR_mknod 133
#define __NR_uselib 134
#define __NR_personality 135
#define __NR_ustat 136
#define __NR_statfs 137
#define __NR_fstatfs 138
#define __NR_sysfs 139
#define __NR_getpriority 140
#define __NR_setpriority 141
#define __NR_sched_setparam 142
#define __NR_sched_getparam 143
#define __NR_sched_setscheduler 144
#define __NR_sched_getscheduler 145
#define __NR_sched_get_priority_max 146
#define __NR_sched_get_priority_min 147
#define __NR_sched_rr_get_interval 148
#define __NR_mlock 149
#define __NR_munlock 150
#define __NR_mlockall 151
#define __NR_munlockall 152
#define __NR_vhangup 153
#define __NR_modify_ldt 154
#define __NR_pivot_root 155
#define __NR__sysctl 156
#define __NR_prctl 157
#define __NR_arch_prctl 158
#define __NR_adjtimex 159
#define __NR_setrlimit 160
#define __NR_chroot 161
#define __NR_sync 162
#define __NR_acct 163
#define __NR_settimeofday 164
#define __NR_mount 165
#define __NR_umount2 166
#define __NR_swapon 167
#define __NR_swapoff 168
#define __NR_reboot 169
#define __NR_sethostname 170
#define __NR_setdomainname 171
#define __NR_iopl 172
#define __NR_ioperm 173
#define __NR_create_module 174
#define __NR_init_module 175
#define __NR_delete_module 176
#define __NR_get_kernel_syms 177
#define __NR_query_module 178
#define __NR_quotactl 179
#define __NR_nfsservctl 180
#define __NR_getpmsg 181
#define __NR_putpmsg 182
#define __NR_afs_syscall 183
#define __NR_tuxcall 184
#define __NR_security 185
#define __NR_gettid 186
#define __NR_readahead 187
#define __NR_setxattr 188
#define __NR_lsetxattr 189
#define __NR_fsetxattr 190
#define __NR_getxattr 191
#define __NR_lgetxattr 192
#define __NR_fgetxattr 193
#define __NR_listxattr 194
#define __NR_llistxattr 195
#define __NR_flistxattr 196
#define __NR_removexattr 197
#define __NR_lremovexattr 198
#define __NR_fremovexattr 199
#define __NR_tkill 200
#define __NR_time 201
#define __NR_futex 202
#define __NR_sched_setaffinity 203
#define __NR_sched_getaffinity 204
#define __NR_set_thread_area 205
#define __NR_io_setup 206
#define __NR_io_destroy 207
#define __NR_io_getevents 208
#define __NR_io_submit 209
#define __NR_io_cancel 210
#define __NR_get_thread_area 211
#define __NR_lookup_dcookie 212
#define __NR_epoll_create 213
#define __NR_epoll_ctl_old 214
#define __NR_epoll_wait_old 215
#define __NR_remap_file_pages 216
#define __NR_getdents64 217
#define __NR_set_tid_address 218
#define __NR_restart_syscall 219
#define __NR_semtimedop 220
#define __NR_fadvise64 221
#define __NR_timer_create 222
#define __NR_timer_settime 223
#define __NR_timer_gettime 224
#define __NR_timer_getoverrun 225
#define __NR_timer_delete 226
#define __NR_clock_settime 227
#define __NR_clock_gettime 228
#define __NR_clock_getres 229
#define __NR_clock_nanosleep 230
#define __NR_exit_group 231
#define __NR_epoll_wait 232
#define __NR_epoll_ctl 233
#define __NR_tgkill 234
#define __NR_utimes 235
#define __NR_vserver 236
#define __NR_mbind 237
#define __NR_set_mempolicy 238
#define __NR_get_mempolicy 239
#define __NR_mq_open 240
#define __NR_mq_unlink 241
#define __NR_mq_timedsend 242
#define __NR_mq_timedreceive 243
#define __NR_mq_notify 244
#define __NR_mq_getsetattr 245
#define __NR_kexec_load 246
#define __NR_waitid 247
#define __NR_add_key 248
#define __NR_request_key 249
#define __NR_keyctl 250
#define __NR_ioprio_set 251
#define __NR_ioprio_get 252
#define __NR_inotify_init 253
#define __NR_inotify_add_watch 254
#define __NR_inotify_rm_watch 255
#define __NR_migrate_pages 256
#define __NR_openat 257
#define __NR_mkdirat 258
#define __NR_mknodat 259
#define __NR_fchownat 260
#define __NR_futimesat 261
#define __NR_newfstatat 262
#define __NR_unlinkat 263
#define __NR_renameat 264
#define __NR_linkat 265
#define __NR_symlinkat 266
#define __NR_readlinkat 267
#define __NR_fchmodat 268
#define __NR_faccessat 269
#define __NR_pselect6 270
#define __NR_ppoll 271
#define __NR_unshare 272
#define __NR_set_robust_list 273
#define __NR_get_robust_list 274
#define __NR_splice 275
#define __NR_tee 276
#define __NR_sync_file_range 277
#define __NR_vmsplice 278
#define __NR_move_pages 279
#define __NR_utimensat 280
#define __NR_epoll_pwait 281
#define __NR_signalfd 282
#define __NR_timerfd_create 283
#define __NR_eventfd 284
#define __NR_fallocate 285
#define __NR_timerfd_settime 286
#define __NR_timerfd_gettime 287
#define __NR_accept4 288
#define __NR_signalfd4 289
#define __NR_eventfd2 290
#define __NR_epoll_create1 291
#define __NR_dup3 292
#define __NR_pipe2 293
#define __NR_inotify_init1 294
#define __NR_preadv 295
#define __NR_pwritev 296
#define __NR_rt_tgsigqueueinfo 297
#define __NR_perf_event_open 298
#define __NR_recvmmsg 299
#define __NR_fanotify_init 300
#define __NR_fanotify_mark 301
#define __NR_prlimit64 302
#define __NR_name_to_handle_at 303
#define __NR_open_by_handle_at 304
#define __NR_clock_adjtime 305
#define __NR_syncfs 306
#define __NR_sendmmsg 307
#define __NR_setns 308
#define __NR_getcpu 309
#define __NR_process_vm_readv 310
#define __NR_process_vm_writev 311
#define __NR_kcmp 312
#define __NR_finit_module 313
#define __NR_sched_setattr 314
#define __NR_sched_getattr 315
#define __NR_renameat2 316
#define __NR_seccomp 317
#define __NR_getrandom 318
#define __NR_memfd_create 319
#define __NR_kexec_file_load 320
#define __NR_bpf 321
#define __NR_execveat 322
#define __NR_userfaultfd 323
#define __NR_membarrier 324
#define __NR_mlock2 325
#define __NR_copy_file_range 326
#define __NR_preadv2 327
#define __NR_pwritev2 328
#define __NR_pkey_mprotect 329
#define __NR_pkey_alloc 330
#define __NR_pkey_free 331
#define __NR_statx 332
#define __NR_io_pgetevents 333
#define __NR_rseq 334
#define __NR_pidfd_send_signal 424
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
#define __NR_open_tree 428
#define __NR_move_mount 429
#define __NR_fsopen 430
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define __NR_pidfd_open 434
#define __NR_clone3 435
#define __NR_close_range 436
#define __NR_openat2 437
#define __NR_pidfd_getfd 438
#define __NR_faccessat2 439
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
#endif // !__FENNIX_KERNEL_LINUX_SYSCALLS_H__

230
syscalls/native.cpp Normal file
View File

@ -0,0 +1,230 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../syscalls.h"
#include "../kernel.h"
#include "../ipc.h"
struct SyscallData
{
const char *Name;
void *Handler;
int RequiredID;
};
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
void sys_exit(SysFrm *, int status);
void *sys_mmap(SysFrm *,
void *addr, size_t len,
int prot, int flags,
int fildes, off_t off);
int sys_munmap(SysFrm *,
void *addr, size_t len);
int sys_mprotect(SysFrm *,
void *addr, size_t len,
int prot);
int sys_open(SysFrm *,
const char *path,
int oflag, mode_t mode);
int sys_close(SysFrm *,
int fildes);
ssize_t sys_read(SysFrm *, int fildes,
void *buf, size_t nbyte);
ssize_t sys_write(SysFrm *, int fildes,
const void *buf,
size_t nbyte);
off_t sys_lseek(SysFrm *, int fildes,
off_t offset, int whence);
int sys_fork(SysFrm *Frame);
static SyscallData NativeSyscallsTable[sc_MaxSyscall] = {
[sc_exit] = {
"exit",
(void *)sys_exit,
UINT16_MAX,
},
[sc_mmap] = {
"mmap",
(void *)sys_mmap,
UINT16_MAX,
},
[sc_munmap] = {
"munmap",
(void *)sys_munmap,
UINT16_MAX,
},
[sc_mprotect] = {
"mprotect",
(void *)sys_mprotect,
UINT16_MAX,
},
[sc_open] = {
"open",
(void *)sys_open,
UINT16_MAX,
},
[sc_close] = {
"close",
(void *)sys_close,
UINT16_MAX,
},
[sc_read] = {
"read",
(void *)sys_read,
UINT16_MAX,
},
[sc_write] = {
"write",
(void *)sys_write,
UINT16_MAX,
},
[sc_lseek] = {
"lseek",
(void *)sys_lseek,
UINT16_MAX,
},
[sc_fork] = {
"fork",
(void *)sys_fork,
UINT16_MAX,
},
};
uintptr_t HandleNativeSyscalls(SysFrm *Frame)
{
#if defined(a64)
if (unlikely(Frame->rax > sc_MaxSyscall))
{
fixme("Syscall %ld not implemented.", Frame->rax);
return -ENOSYS;
}
SyscallData Syscall = NativeSyscallsTable[Frame->rax];
uintptr_t (*call)(SysFrm *, uintptr_t, ...) =
r_cst(uintptr_t(*)(SysFrm *, uintptr_t, ...),
Syscall.Handler);
if (unlikely(!call))
{
error("Syscall %s(%d) not implemented.",
Syscall.Name, Frame->rax);
return -ENOSYS;
}
int euid = thisProcess->Security.Effective.UserID;
int egid = thisProcess->Security.Effective.GroupID;
int reqID = Syscall.RequiredID;
if (euid > reqID || egid > reqID)
{
warn("Process %s(%d) tried to access a system call \"%s\" with insufficient privileges.",
thisProcess->Name, thisProcess->ID, Syscall.Name);
debug("Required: %d; Effective u:%d, g:%d", reqID, euid, egid);
return -EPERM;
}
debug("> [%d:\"%s\"]( %#lx %#lx %#lx %#lx %#lx %#lx )",
Frame->rax, Syscall.Name,
Frame->rdi, Frame->rsi, Frame->rdx,
Frame->r10, Frame->r8, Frame->r9);
long sc_ret = call(Frame,
Frame->rdi, Frame->rsi, Frame->rdx,
Frame->r10, Frame->r8, Frame->r9);
debug("< [%d:\"%s\"] = %d",
Frame->rax, Syscall.Name, sc_ret);
return sc_ret;
#elif defined(a32)
if (unlikely(Frame->eax > sc_MaxSyscall))
{
fixme("Syscall %ld not implemented.", Frame->eax);
return -ENOSYS;
}
SyscallData Syscall = NativeSyscallsTable[Frame->eax];
uintptr_t (*call)(SysFrm *, uintptr_t, ...) =
r_cst(uintptr_t(*)(SysFrm *, uintptr_t, ...),
Syscall.Handler);
if (unlikely(!call))
{
error("Syscall %s(%d) not implemented.",
Syscall.Name, Frame->eax);
return -ENOSYS;
}
int euid = thisProcess->Security.Effective.UserID;
int egid = thisProcess->Security.Effective.GroupID;
int reqID = Syscall.RequiredID;
if (euid > reqID || egid > reqID)
{
warn("Process %s(%d) tried to access a system call \"%s\" with insufficient privileges.",
thisProcess->Name, thisProcess->ID, Syscall.Name);
debug("Required: %d; Effective u:%d, g:%d", reqID, euid, egid);
return -EPERM;
}
debug("> [%d:\"%s\"]( %#x %#x %#x %#x %#x %#x )",
Frame->eax, Syscall.Name,
Frame->ebx, Frame->ecx, Frame->edx,
Frame->esi, Frame->edi, Frame->ebp);
int sc_ret = call(Frame,
Frame->ebx, Frame->ecx, Frame->edx,
Frame->esi, Frame->edi, Frame->ebp);
debug("< [%d:\"%s\"] = %d",
Frame->eax, Syscall.Name, sc_ret);
return sc_ret;
#elif defined(aa64)
return -ENOSYS;
#endif
}

54
syscalls/native/close.cpp Normal file
View File

@ -0,0 +1,54 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
#include "../../ipc.h"
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/close.html */
int sys_close(SysFrm *,
int fildes)
{
function("%d", fildes);
PCB *pcb = thisProcess;
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
return fdt->_close(fildes);
}

213
syscalls/native/execve.cpp Normal file
View File

@ -0,0 +1,213 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <limits.h>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
#include "../../ipc.h"
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using vfs::RefNode;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
/* https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html */
int sys_execve(SysFrm *Frame, const char *path,
char *const argv[], char *const envp[])
{
PCB *pcb = thisProcess;
Memory::Virtual vmm(pcb->PageTable);
if (path == nullptr ||
!vmm.Check((void *)path, Memory::US) ||
!vmm.Check((void *)argv, Memory::US) ||
!vmm.Check((void *)envp, Memory::US))
return -ENOENT;
const char *safe_path;
char **safe_argv;
char **safe_envp;
safe_path = (const char *)pcb->vma->RequestPages(1);
safe_argv = (char **)pcb->vma->RequestPages(TO_PAGES(MAX_ARG));
safe_envp = (char **)pcb->vma->RequestPages(TO_PAGES(MAX_ARG));
{
Memory::SwapPT swap(pcb->PageTable);
size_t len = strlen(path);
memset((void *)safe_path, 0, PAGE_SIZE);
memcpy((void *)safe_path, path, len);
const char *arg;
char *n_arg;
for (int i = 0; argv[i] != nullptr; i++)
{
arg = argv[i];
size_t len = strlen(arg);
n_arg = (char *)pcb->vma->RequestPages(TO_PAGES(len));
memcpy((void *)n_arg, arg, len);
n_arg[len] = '\0';
safe_argv[i] = n_arg;
if (likely(i < MAX_ARG - 1))
safe_argv[i + 1] = nullptr;
}
for (int i = 0; envp[i] != nullptr; i++)
{
arg = envp[i];
size_t len = strlen(arg);
n_arg = (char *)pcb->vma->RequestPages(TO_PAGES(len));
memcpy((void *)n_arg, arg, len);
n_arg[len] = '\0';
safe_envp[i] = n_arg;
if (likely(i < MAX_ARG - 1))
safe_envp[i + 1] = nullptr;
}
}
function("%s %#lx %#lx", safe_path, safe_argv, safe_envp);
#ifdef DEBUG
for (int i = 0; safe_argv[i] != nullptr; i++)
debug("safe_argv[%d]: %s", i, safe_argv[i]);
for (int i = 0; safe_envp[i] != nullptr; i++)
debug("safe_envp[%d]: %s", i, safe_envp[i]);
#endif
RefNode *File = fs->Open(safe_path,
pcb->CurrentWorkingDirectory);
if (!File)
{
error("File not found");
return -ENOENT;
}
char shebang_magic[2];
File->read((uint8_t *)shebang_magic, 2);
if (shebang_magic[0] == '#' && shebang_magic[1] == '!')
{
char *orig_path = (char *)pcb->vma->RequestPages(TO_PAGES(strlen(path) + 1));
memcpy(orig_path, path, strlen(path) + 1);
char *shebang = (char *)safe_path;
size_t shebang_len = 0;
constexpr int shebang_len_max = 255;
File->seek(2, SEEK_SET);
off_t shebang_off = 2;
while (true)
{
char c;
if (File->node->read((uint8_t *)&c, 1, shebang_off) == 0)
break;
if (c == '\n' || shebang_len == shebang_len_max)
break;
shebang[shebang_len++] = c;
shebang_off++;
}
shebang[shebang_len] = '\0';
debug("Shebang: %s", shebang);
char **c_safe_argv = (char **)pcb->vma->RequestPages(TO_PAGES(MAX_ARG));
int i = 0;
for (; safe_argv[i] != nullptr; i++)
{
size_t arg_len = strlen(safe_argv[i]);
char *c_arg = (char *)pcb->vma->RequestPages(TO_PAGES(arg_len));
memcpy((void *)c_arg, safe_argv[i], arg_len);
c_arg[arg_len] = '\0';
c_safe_argv[i] = c_arg;
debug("c_safe_argv[%d]: %s", i, c_safe_argv[i]);
}
c_safe_argv[i] = nullptr;
char *token = strtok(shebang, " ");
i = 0;
while (token != nullptr)
{
size_t len = strlen(token);
char *t_arg = (char *)pcb->vma->RequestPages(TO_PAGES(len));
memcpy((void *)t_arg, token, len);
t_arg[len] = '\0';
safe_argv[i++] = t_arg;
token = strtok(nullptr, " ");
}
safe_argv[i++] = orig_path;
for (int j = 1; c_safe_argv[j] != nullptr; j++)
{
safe_argv[i++] = c_safe_argv[j];
debug("clone: safe_argv[%d]: %s",
i, safe_argv[i - 1]);
}
safe_argv[i] = nullptr;
delete File;
return sys_execve(Frame, safe_argv[0],
(char *const *)safe_argv,
(char *const *)safe_envp);
}
int ret = Execute::Spawn((char *)safe_path,
(const char **)safe_argv,
(const char **)safe_envp,
pcb->Parent, pcb->Info.Compatibility);
if (ret < 0)
{
error("Failed to spawn");
delete File;
return ret;
}
delete File;
Tasking::Task *ctx = pcb->GetContext();
ctx->Sleep(1000);
pcb->State = Tasking::Zombie;
pcb->ExitCode = 0;
while (true)
ctx->Yield();
__builtin_unreachable();
}

62
syscalls/native/exit.cpp Normal file
View File

@ -0,0 +1,62 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
#include "../../ipc.h"
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/exit.html */
__noreturn void sys_exit(SysFrm *, int status)
{
TCB *t = thisThread;
trace("Userspace thread %s(%d) exited with code %d (%#x)",
t->Name,
t->ID, status,
status < 0 ? -status : status);
t->ExitCode = status;
t->KeepTime = TimeManager->CalculateTarget(10, Time::Seconds);
t->State = Terminated;
while (true)
t->GetContext()->Yield();
__builtin_unreachable();
}

141
syscalls/native/fork.cpp Normal file
View File

@ -0,0 +1,141 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
#include "../../ipc.h"
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/fork.html */
int sys_fork(SysFrm *Frame)
{
assert(Frame != nullptr);
#ifdef a32
return -ENOSYS;
#endif
PCB *Parent = thisThread->Parent;
TCB *Thread = thisThread;
void *ProcSymTable = nullptr;
if (Parent->ELFSymbolTable)
ProcSymTable = Parent->ELFSymbolTable->GetImage();
PCB *NewProcess =
TaskManager->CreateProcess(Parent,
Parent->Name,
Parent->Security.ExecutionMode,
ProcSymTable);
if (!NewProcess)
{
error("Failed to create process for fork");
return -EAGAIN;
}
NewProcess->IPC->Fork(Parent->IPC);
TCB *NewThread =
TaskManager->CreateThread(NewProcess,
0,
nullptr,
nullptr,
std::vector<AuxiliaryVector>(),
Thread->Info.Architecture,
Thread->Info.Compatibility,
true);
NewThread->Rename(Thread->Name);
if (!NewThread)
{
error("Failed to create thread for fork");
return -EAGAIN;
}
TaskManager->UpdateFrame();
/* This if statement will overwrite
most of the registers except rcx
and r8-r15 */
if (thisThread->ID == NewThread->ID)
{
/* We can't just return 0; because the
gsTCB->SyscallStack is no
longer valid */
#if defined(a64)
asmv("movq $0, %rax\n"); /* Return 0 */
asmv("movq %r8, %rsp\n"); /* Restore stack pointer */
asmv("movq %r8, %rbp\n"); /* Restore base pointer */
asmv("swapgs\n"); /* Swap GS back to the user GS */
asmv("sti\n"); /* Enable interrupts */
asmv("sysretq\n"); /* Return to rcx address in user mode */
#elif defined(a32)
#warning "sys_fork not implemented for i386"
#endif
__builtin_unreachable();
}
memcpy(&NewThread->FPU, &Thread->FPU, sizeof(CPU::x64::FXState));
NewThread->Stack->Fork(Thread->Stack);
NewThread->Info.Architecture = Thread->Info.Architecture;
NewThread->Info.Compatibility = Thread->Info.Compatibility;
NewThread->Registers = Thread->Registers;
#if defined(a64)
/* For sysretq */
NewThread->Registers.rcx = Frame->ReturnAddress;
NewThread->Registers.r8 = Frame->StackPointer;
#endif
if (Thread->Security.IsCritical)
NewThread->SetCritical(true);
#ifdef a86
NewThread->GSBase = NewThread->ShadowGSBase;
NewThread->ShadowGSBase = Thread->ShadowGSBase;
NewThread->FSBase = Thread->FSBase;
#endif
debug("Forked thread \"%s\"(%d) to \"%s\"(%d)",
Thread->Name, Thread->ID,
NewThread->Name, NewThread->ID);
NewThread->State = Ready;
return (int)NewProcess->ID;
}

54
syscalls/native/lseek.cpp Normal file
View File

@ -0,0 +1,54 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
#include "../../ipc.h"
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/lseek.html */
off_t sys_lseek(SysFrm *, int fildes,
off_t offset, int whence)
{
function("%d, %d, %d", fildes, offset, whence);
PCB *pcb = thisProcess;
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
return fdt->_lseek(fildes, offset, whence);
}

113
syscalls/native/mmap.cpp Normal file
View File

@ -0,0 +1,113 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
#include "../../ipc.h"
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/mmap.html */
void *sys_mmap(SysFrm *,
void *addr, size_t len,
int prot, int flags,
int fildes, off_t off)
{
if (len == 0)
return (void *)-EINVAL;
if (fildes != -1)
return (void *)-ENOSYS;
bool p_None = prot & sc_PROT_NONE;
bool p_Read = prot & sc_PROT_READ;
bool p_Write = prot & sc_PROT_WRITE;
bool p_Exec = prot & sc_PROT_EXEC;
bool m_Shared = flags & sc_MAP_SHARED;
bool m_Private = flags & sc_MAP_PRIVATE;
bool m_Fixed = flags & sc_MAP_FIXED;
bool m_Anon = flags & sc_MAP_ANONYMOUS;
UNUSED(p_None);
UNUSED(m_Anon);
debug("N:%d R:%d W:%d E:%d",
p_None, p_Read, p_Write,
p_Exec);
debug("S:%d P:%d F:%d A:%d",
m_Shared, m_Private,
m_Fixed, m_Anon);
int UnknownFlags = flags & ~(sc_MAP_SHARED |
sc_MAP_PRIVATE |
sc_MAP_FIXED |
sc_MAP_ANONYMOUS);
if (UnknownFlags)
{
debug("Unknown flags: %x", UnknownFlags);
return (void *)-EINVAL;
}
if (len > PAGE_SIZE_2M)
fixme("large page 2 MiB (requested %d)",
TO_MiB(len));
else if (len > PAGE_SIZE_1G)
fixme("huge page 1 GiB (requested %d)",
TO_GiB(len));
if (off % PAGE_SIZE)
return (void *)-EINVAL;
if (uintptr_t(addr) % PAGE_SIZE && m_Fixed)
return (void *)-EINVAL;
if ((m_Shared && m_Private) ||
(!m_Shared && !m_Private))
return (void *)-EINVAL;
Tasking::PCB *pcb = thisProcess;
Memory::VirtualMemoryArea *vma = pcb->vma;
intptr_t ret = (intptr_t)vma->CreateCoWRegion(addr, len,
p_Read, p_Write, p_Exec,
m_Fixed, m_Shared);
return (void *)ret;
}

View File

@ -0,0 +1,107 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
#include "../../ipc.h"
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/mprotect.html */
int sys_mprotect(SysFrm *,
void *addr, size_t len, int prot)
{
if (len == 0)
return -EINVAL;
if (uintptr_t(addr) % PAGE_SIZE)
return -EINVAL;
bool p_None = prot & sc_PROT_NONE;
bool p_Read = prot & sc_PROT_READ;
bool p_Write = prot & sc_PROT_WRITE;
// bool p_Exec = prot & sc_PROT_EXEC;
Tasking::PCB *pcb = thisProcess;
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
for (uintptr_t i = uintptr_t(addr);
i < uintptr_t(addr) + len;
i += PAGE_SIZE)
{
if (likely(!vmm.Check((void *)i, Memory::G)))
{
Memory::PageTableEntry *pte = vmm.GetPTE(addr);
if (!pte->Present ||
(!pte->UserSupervisor && p_Read) ||
(!pte->ReadWrite && p_Write))
{
debug("Page %p is not mapped with the correct permissions",
(void *)i);
return -EACCES;
}
pte->Present = p_None;
pte->UserSupervisor = p_Read;
pte->ReadWrite = p_Write;
// pte->ExecuteDisable = p_Exec;
#if defined(a64)
CPU::x64::invlpg(addr);
#elif defined(a32)
CPU::x32::invlpg(addr);
#elif defined(aa64)
asmv("dsb sy");
asmv("tlbi vae1is, %0"
:
: "r"(addr)
: "memory");
asmv("dsb sy");
asmv("isb");
#endif
}
else
{
warn("%p is a global page", (void *)i);
return -ENOMEM;
}
}
return 0;
}

View File

@ -0,0 +1,74 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
#include "../../ipc.h"
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/munmap.html */
int sys_munmap(SysFrm *,
void *addr, size_t len)
{
if (uintptr_t(addr) % PAGE_SIZE)
return -EINVAL;
if (len == 0)
return -EINVAL;
Tasking::PCB *pcb = thisProcess;
Memory::VirtualMemoryArea *vma = pcb->vma;
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
for (uintptr_t i = uintptr_t(addr);
i < uintptr_t(addr) + len;
i += PAGE_SIZE)
{
if (likely(!vmm.Check((void *)i, Memory::G)))
vmm.Remap((void *)i, (void *)i, Memory::P | Memory::RW);
else
warn("%p is a global page", (void *)i);
}
/* TODO: Check if the page is allocated
and not only mapped */
vma->FreePages((void *)addr, TO_PAGES(len) + 1);
return 0;
}

64
syscalls/native/open.cpp Normal file
View File

@ -0,0 +1,64 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
#include "../../ipc.h"
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/open.html */
int sys_open(SysFrm *,
const char *path,
int oflag, mode_t mode)
{
const char *safe_path = nullptr;
Tasking::PCB *pcb = thisProcess;
Memory::SmartHeap sh(512, pcb->vma);
safe_path = (const char *)sh.Get();
{
Memory::SwapPT swap(pcb->PageTable);
size_t len = strlen(path);
memcpy((void *)safe_path, path, len);
}
function("%s, %d, %d", safe_path, oflag, mode);
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
return fdt->_open(safe_path, oflag, mode);
}

68
syscalls/native/read.cpp Normal file
View File

@ -0,0 +1,68 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
#include "../../ipc.h"
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/read.html */
ssize_t sys_read(SysFrm *, int fildes,
void *buf, size_t nbyte)
{
void *safe_buf = nullptr;
Tasking::PCB *pcb = thisProcess;
Memory::SmartHeap sh(nbyte, pcb->vma);
safe_buf = sh.Get();
function("%d, %p, %d", fildes, buf, nbyte);
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
ssize_t ret = fdt->_read(fildes, safe_buf, nbyte);
if (ret >= 0)
fdt->_lseek(fildes, ret, SEEK_CUR);
else
return ret;
{
Memory::SwapPT swap(pcb->PageTable);
memcpy(buf, safe_buf, nbyte);
}
return ret;
}

65
syscalls/native/write.cpp Normal file
View File

@ -0,0 +1,65 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
#include "../../ipc.h"
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using Tasking::TaskState::Terminated;
using namespace Memory;
#define SysFrm SyscallsFrame
#if defined(a64)
typedef long arch_t;
#elif defined(a32)
typedef int arch_t;
#endif
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/write.html */
ssize_t sys_write(SysFrm *, int fildes,
const void *buf, size_t nbyte)
{
const void *safe_buf = nullptr;
Tasking::PCB *pcb = thisProcess;
Memory::SmartHeap sh(nbyte, pcb->vma);
safe_buf = sh.Get();
{
Memory::SwapPT swap(pcb->PageTable);
memcpy((void *)safe_buf, buf, nbyte);
}
function("%d, %p, %d", fildes, buf, nbyte);
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
ssize_t ret = fdt->_write(fildes, safe_buf, nbyte);
if (ret)
fdt->_lseek(fildes, ret, SEEK_CUR);
return ret;
}

99
syscalls/syscalls.cpp Normal file
View File

@ -0,0 +1,99 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <debug.h>
#include "../kernel.h"
class AutoSwitchPageTable
{
private:
uintptr_t Original;
public:
AutoSwitchPageTable()
{
#if defined(a86)
asmv("mov %%cr3, %0"
: "=r"(Original));
asmv("mov %0, %%cr3"
:
: "r"(KernelPageTable));
#endif
}
~AutoSwitchPageTable()
{
#if defined(a86)
asmv("mov %0, %%cr3"
:
: "r"(Original));
#endif
}
};
extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame)
{
/* Automatically switch to kernel page table
and switch back when this function returns. */
AutoSwitchPageTable PageSwitcher;
uint64_t _ctime = TimeManager->GetCounter();
Tasking::TaskInfo *Ptinfo = &thisProcess->Info;
Tasking::TaskInfo *Ttinfo = &thisThread->Info;
uintptr_t ret;
if (Config.UseLinuxSyscalls)
{
ret = HandleLinuxSyscalls(Frame);
goto Ret;
}
switch (Ttinfo->Compatibility)
{
case Tasking::TaskCompatibility::Native:
{
ret = HandleNativeSyscalls(Frame);
break;
}
case Tasking::TaskCompatibility::Linux:
{
ret = HandleLinuxSyscalls(Frame);
break;
}
case Tasking::TaskCompatibility::Windows:
{
error("Windows compatibility not implemented yet.");
assert(false);
break;
}
default:
{
error("Unknown compatibility mode!");
assert(false);
break;
}
}
Ret:
Ptinfo->KernelTime += TimeManager->GetCounter() - _ctime;
Ttinfo->KernelTime += TimeManager->GetCounter() - _ctime;
return ret;
}