summaryrefslogtreecommitdiff
path: root/kernel/cpu
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-06-26 21:34:40 +0200
committerAnton Kling <anton@kling.gg>2024-06-26 21:34:40 +0200
commite15065fe45f8004adcc8b69bbbe680ced0d530a1 (patch)
tree19dab20babd5169a8266faf133d41a4ebd61f1f6 /kernel/cpu
parent2e2f89c7508dede2c970e6061c2f66d4536162ca (diff)
Kernel: Move all syscalls into one file
Diffstat (limited to 'kernel/cpu')
-rw-r--r--kernel/cpu/syscall.c372
-rw-r--r--kernel/cpu/syscall.h54
2 files changed, 371 insertions, 55 deletions
diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c
index 4a446d5..6d2b150 100644
--- a/kernel/cpu/syscall.c
+++ b/kernel/cpu/syscall.c
@@ -2,22 +2,392 @@
// valid.
#include <assert.h>
#include <cpu/syscall.h>
+#include <drivers/pit.h>
#include <drivers/pst.h>
#include <errno.h>
#include <fcntl.h>
+#include <fs/shm.h>
#include <fs/tmpfs.h>
#include <fs/vfs.h>
#include <interrupts.h>
#include <kmalloc.h>
+#include <math.h>
#include <network/ethernet.h>
#include <network/tcp.h>
+#include <network/udp.h>
+#include <poll.h>
+#include <random.h>
#include <socket.h>
#include <string.h>
-#include <syscalls.h>
#include <typedefs.h>
+typedef struct SYS_CLOCK_GETTIME_PARAMS {
+ clockid_t clk;
+ struct timespec *ts;
+} __attribute__((packed)) SYS_CLOCK_GETTIME_PARAMS;
+
+struct two_args {
+ u32 a;
+ u32 b;
+};
+
+typedef struct SYS_OPEN_PARAMS {
+ const char *file;
+ int flags;
+ int mode;
+} __attribute__((packed)) SYS_OPEN_PARAMS;
+
+typedef struct SYS_PREAD_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+ size_t offset;
+} __attribute__((packed)) SYS_PREAD_PARAMS;
+
+typedef struct SYS_READ_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+} __attribute__((packed)) SYS_READ_PARAMS;
+
+typedef struct SYS_PWRITE_PARAMS {
+ int fd;
+ const void *buf;
+ size_t count;
+ size_t offset;
+} __attribute__((packed)) SYS_PWRITE_PARAMS;
+
+typedef struct SYS_WRITE_PARAMS {
+ int fd;
+ const void *buf;
+ size_t count;
+} __attribute__((packed)) SYS_WRITE_PARAMS;
+
+typedef struct SYS_EXEC_PARAMS {
+ const char *path;
+ char **argv;
+} __attribute__((packed)) SYS_EXEC_PARAMS;
+
+typedef struct SYS_DUP2_PARAMS {
+ int org_fd;
+ int new_fd;
+} __attribute__((packed)) SYS_DUP2_PARAMS;
+
+typedef struct SYS_OPENPTY_PARAMS {
+ int *amaster;
+ int *aslave;
+ char *name;
+ /*const struct termios*/ void *termp;
+ /*const struct winsize*/ void *winp;
+} __attribute__((packed)) SYS_OPENPTY_PARAMS;
+
+typedef struct SYS_POLL_PARAMS {
+ struct pollfd *fds;
+ size_t nfds;
+ int timeout;
+} __attribute__((packed)) SYS_POLL_PARAMS;
+
+typedef struct SYS_MMAP_PARAMS {
+ void *addr;
+ size_t length;
+ int prot;
+ int flags;
+ int fd;
+ size_t offset;
+} __attribute__((packed)) SYS_MMAP_PARAMS;
+
+typedef struct SYS_SOCKET_PARAMS {
+ int domain;
+ int type;
+ int protocol;
+} __attribute__((packed)) SYS_SOCKET_PARAMS;
+
+typedef struct SYS_BIND_PARAMS {
+ int sockfd;
+ const struct sockaddr *addr;
+ socklen_t addrlen;
+} __attribute__((packed)) SYS_BIND_PARAMS;
+
+typedef struct SYS_ACCEPT_PARAMS {
+ int socket;
+ struct sockaddr *address;
+ socklen_t *address_len;
+} __attribute__((packed)) SYS_ACCEPT_PARAMS;
+
+typedef struct SYS_SHM_OPEN_PARAMS {
+ const char *name;
+ int oflag;
+ mode_t mode;
+} __attribute__((packed)) SYS_SHM_OPEN_PARAMS;
+
+typedef struct SYS_FTRUNCATE_PARAMS {
+ int fildes;
+ size_t length;
+} __attribute__((packed)) SYS_FTRUNCATE_PARAMS;
+
#pragma GCC diagnostic ignored "-Wpedantic"
+int syscall_accept(SYS_ACCEPT_PARAMS *args) {
+ return accept(args->socket, args->address, args->address_len);
+}
+
+int syscall_bind(SYS_BIND_PARAMS *args) {
+ return bind(args->sockfd, args->addr, args->addrlen);
+}
+
+int syscall_chdir(const char *path) {
+ return vfs_chdir(path);
+}
+
+int syscall_clock_gettime(SYS_CLOCK_GETTIME_PARAMS *args) {
+ // FIXME: Actually implement this
+ if (args->ts) {
+ args->ts->tv_sec = 0;
+ args->ts->tv_nsec = 0;
+ }
+ return 0;
+}
+
+int syscall_fstat(int fd, struct stat *buf) {
+ if (!mmu_is_valid_userpointer(buf, sizeof(struct stat))) {
+ return -EPERM; // TODO: Is this correct? The spec says nothing about
+ // this case.
+ }
+ return vfs_fstat(fd, buf);
+}
+
+int syscall_ftruncate(int fd, size_t length) {
+ return vfs_ftruncate(fd, length);
+}
+
+char *syscall_getcwd(char *buf, size_t size) {
+ const char *cwd = current_task->current_working_directory;
+ size_t len = min(size, strlen(cwd));
+ strlcpy(buf, current_task->current_working_directory, len);
+ return buf;
+}
+
+int syscall_isatty(int fd) {
+ vfs_fd_t *fd_ptr = get_vfs_fd(fd, NULL);
+ if (!fd_ptr) {
+ return -EBADF;
+ }
+ if (!fd_ptr->is_tty) {
+ return -ENOTTY;
+ }
+ return 1;
+}
+
+int syscall_kill(int fd, int sig) {
+ vfs_fd_t *fd_ptr = get_vfs_fd(fd, NULL);
+ if (!fd_ptr) {
+ return -EBADF;
+ }
+ if (!fd_ptr->inode->send_signal) {
+ return -EBADF;
+ }
+ return process_signal(fd_ptr, sig);
+}
+
+// FIXME: These should be in a shared header file with libc
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+int syscall_lseek(int fd, int offset, int whence) {
+ vfs_fd_t *fd_ptr = get_vfs_fd(fd, NULL);
+ if (!fd_ptr) {
+ return -EBADF;
+ }
+
+ off_t ret_offset = fd_ptr->offset;
+ switch (whence) {
+ case SEEK_SET:
+ ret_offset = offset;
+ break;
+ case SEEK_CUR:
+ ret_offset += offset;
+ break;
+ case SEEK_END:
+ assert(fd_ptr->inode);
+ ret_offset = fd_ptr->inode->file_size + offset;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ fd_ptr->offset = ret_offset;
+ return ret_offset;
+}
+
+int syscall_mkdir(const char *path, int mode) {
+ return vfs_mkdir(path, mode);
+}
+
+void *syscall_mmap(SYS_MMAP_PARAMS *args) {
+ return mmap(args->addr, args->length, args->prot, args->flags, args->fd,
+ args->offset);
+}
+
+void syscall_msleep(u32 ms) {
+ current_task->sleep_until = pit_num_ms() + ms;
+ switch_task();
+}
+
+int syscall_munmap(void *addr, size_t length) {
+ return munmap(addr, length);
+}
+
+int syscall_open(const char *file, int flags, mode_t mode) {
+ const char *_file = copy_and_allocate_user_string(file);
+ if (!_file) {
+ return -EFAULT;
+ }
+ int _flags = flags;
+ int _mode = mode;
+ int rc = vfs_open(_file, _flags, _mode);
+ kfree((void *)_file);
+ return rc;
+}
+
+int syscall_open_process(int pid) {
+ // TODO: Permission check
+ process_t *process = (process_t *)ready_queue;
+ for (; process; process = process->next) {
+ if (pid == process->pid) {
+ break;
+ }
+ }
+ if (!process) {
+ return -ESRCH;
+ }
+
+ vfs_inode_t *inode = vfs_create_inode(
+ process->pid, 0 /*type*/, 0 /*has_data*/, 0 /*can_write*/, 1 /*is_open*/,
+ process /*internal_object*/, 0 /*file_size*/, NULL /*open*/,
+ NULL /*create_file*/, NULL /*read*/, NULL /*write*/, NULL /*close*/,
+ NULL /*create_directory*/, NULL /*get_vm_object*/, NULL /*truncate*/,
+ NULL /*stat*/, process_signal, NULL /*connect*/);
+ int rc = vfs_create_fd(0, 0, 0, inode, NULL);
+ assert(rc >= 0);
+ return rc;
+}
+
+int syscall_poll(SYS_POLL_PARAMS *args) {
+ struct pollfd *fds = args->fds;
+ size_t nfds = args->nfds;
+ int timeout = args->timeout;
+ return poll(fds, nfds, timeout);
+}
+
+int syscall_pwrite(int fd, const char *buf, size_t count, size_t offset) {
+ return vfs_pwrite(fd, (char *)buf, count, offset);
+}
+
+void syscall_randomfill(void *buffer, u32 size) {
+ get_random(buffer, size);
+}
+
+size_t syscall_recvfrom(
+ int socket, void *buffer, size_t length, int flags,
+ struct two_args
+ *extra_args /*struct sockaddr *address, socklen_t *address_len*/) {
+
+ struct sockaddr *address = (struct sockaddr *)extra_args->a;
+ socklen_t *address_len = (socklen_t *)extra_args->b;
+
+ if (flags & MSG_WAITALL) {
+ struct pollfd fds[1];
+ fds[0].fd = socket;
+ fds[0].events = POLLIN;
+ poll(fds, 1, 0);
+ }
+
+ u16 data_length;
+ socklen_t tmp_socklen;
+ vfs_pread(socket, &tmp_socklen, sizeof(socklen_t), 0);
+ if (address_len) {
+ *address_len = tmp_socklen;
+ }
+ if (address) {
+ vfs_pread(socket, address, tmp_socklen, 0);
+ } else {
+ // We still have to throwaway the data.
+ char devnull[100];
+ for (; tmp_socklen;) {
+ int rc = vfs_pread(socket, devnull, min(tmp_socklen, 100), 0);
+ assert(rc >= 0);
+ tmp_socklen -= rc;
+ }
+ }
+
+ vfs_pread(socket, &data_length, sizeof(data_length), 0);
+ // If it is reading less than the packet length that could cause
+ // problems as the next read will not be put at a new header. Luckily
+ // it seems as if other UNIX systems can discard the rest of the
+ // packet if not read.
+
+ // Read in the data requested
+ int read_len = min(length, data_length);
+ int rc = vfs_pread(socket, buffer, read_len, 0);
+ // Discard the rest of the packet
+ int rest = data_length - read_len;
+ char devnull[100];
+ for (; rest;) {
+ int rc = vfs_pread(socket, devnull, 100, 0);
+ assert(rc >= 0);
+ rest -= rc;
+ }
+ return rc;
+}
+
+size_t syscall_sendto(int socket, const void *message, size_t length,
+ int flags, struct two_args *extra_args /*
+ const struct sockaddr *dest_addr,
+ socklen_t dest_len*/) {
+ const struct sockaddr *dest_addr = (const struct sockaddr *)extra_args->a;
+ socklen_t dest_len = (socklen_t)extra_args->b;
+ (void)dest_len;
+ vfs_fd_t *fd = get_vfs_fd(socket, NULL);
+ assert(fd);
+ SOCKET *s = (SOCKET *)fd->inode->internal_object;
+ OPEN_INET_SOCKET *inet = s->child;
+ assert(inet);
+ struct sockaddr_in in;
+ in.sin_addr.s_addr = inet->address;
+ in.sin_port = inet->port;
+ send_udp_packet(&in, (const struct sockaddr_in *)dest_addr, message, length);
+ return length; // FIXME: This is probably not true.
+}
+
+int syscall_shm_open(SYS_SHM_OPEN_PARAMS *args) {
+ return shm_open(args->name, args->oflag, args->mode);
+}
+
+int syscall_sigaction(int sig, const struct sigaction *restrict act,
+ struct sigaction *restrict oact) {
+ set_signal_handler(sig, act->sa_handler);
+ return 0;
+}
+
+int syscall_socket(SYS_SOCKET_PARAMS *args) {
+ return socket(args->domain, args->type, args->protocol);
+}
+
+u32 syscall_uptime(void) {
+ return (u32)pit_num_ms();
+}
+
+int syscall_write(int fd, const char *buf, size_t count) {
+ vfs_fd_t *fd_ptr = get_vfs_fd(fd, NULL);
+ if (!fd_ptr) {
+ return -EBADF;
+ }
+ int rc = vfs_pwrite(fd, (char *)buf, count, fd_ptr->offset);
+ fd_ptr->offset += rc;
+ return rc;
+}
+
int syscall_exec(SYS_EXEC_PARAMS *args) {
const char *filename = copy_and_allocate_user_string(args->path);
diff --git a/kernel/cpu/syscall.h b/kernel/cpu/syscall.h
index 3568e51..7dd7229 100644
--- a/kernel/cpu/syscall.h
+++ b/kernel/cpu/syscall.h
@@ -3,57 +3,3 @@
#include <typedefs.h>
void syscalls_init(void);
-
-typedef struct SYS_OPEN_PARAMS {
- char *file;
- int flags;
- int mode;
-} __attribute__((packed)) SYS_OPEN_PARAMS;
-
-typedef struct SYS_PREAD_PARAMS {
- int fd;
- void *buf;
- size_t count;
- size_t offset;
-} __attribute__((packed)) SYS_PREAD_PARAMS;
-
-typedef struct SYS_READ_PARAMS {
- int fd;
- void *buf;
- size_t count;
-} __attribute__((packed)) SYS_READ_PARAMS;
-
-typedef struct SYS_PWRITE_PARAMS {
- int fd;
- void *buf;
- size_t count;
- size_t offset;
-} __attribute__((packed)) SYS_PWRITE_PARAMS;
-
-typedef struct SYS_WRITE_PARAMS {
- int fd;
- void *buf;
- size_t count;
-} __attribute__((packed)) SYS_WRITE_PARAMS;
-
-typedef struct SYS_EXEC_PARAMS {
- char *path;
- char **argv;
-} __attribute__((packed)) SYS_EXEC_PARAMS;
-
-typedef struct SYS_WAIT_PARAMS {
- int *status;
-} __attribute__((packed)) SYS_WAIT_PARAMS;
-
-typedef struct SYS_DUP2_PARAMS {
- int org_fd;
- int new_fd;
-} __attribute__((packed)) SYS_DUP2_PARAMS;
-
-typedef struct SYS_OPENPTY_PARAMS {
- int *amaster;
- int *aslave;
- char *name;
- /*const struct termios*/ void *termp;
- /*const struct winsize*/ void *winp;
-} __attribute__((packed)) SYS_OPENPTY_PARAMS;