2021-11-08 22:31:57 +01:00
|
|
|
#include "syscall.h"
|
2024-02-13 00:19:39 +01:00
|
|
|
#include "kernel.h"
|
2021-11-06 00:13:40 +01:00
|
|
|
#include "keyboard.h"
|
2021-11-02 21:57:57 +01:00
|
|
|
#include "klibc.h"
|
2024-02-13 00:19:39 +01:00
|
|
|
#include "paging.h"
|
2022-08-09 16:15:00 +02:00
|
|
|
#include "process.h"
|
2021-11-02 21:57:57 +01:00
|
|
|
#include "stdarg.h"
|
|
|
|
#include "thread.h"
|
2022-08-09 16:15:00 +02:00
|
|
|
#include "types.h"
|
2023-03-24 23:43:09 +01:00
|
|
|
#include "uaccess.h"
|
2022-08-09 16:15:00 +02:00
|
|
|
#include "uaddrspace.h"
|
2023-11-10 09:01:55 +01:00
|
|
|
#include "zero.h"
|
|
|
|
|
2021-11-08 22:31:57 +01:00
|
|
|
int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|
|
|
{
|
2021-11-02 21:57:57 +01:00
|
|
|
|
2021-11-08 23:22:03 +01:00
|
|
|
int ret = 0;
|
2021-11-02 21:57:57 +01:00
|
|
|
|
|
|
|
switch (syscallId) {
|
2021-11-08 22:31:57 +01:00
|
|
|
case SYSCALL_ID_EXIT: {
|
2021-11-02 21:57:57 +01:00
|
|
|
uint status;
|
2021-11-05 23:02:23 +01:00
|
|
|
ret = syscallGet1arg(userCtx, &status);
|
2021-11-08 22:31:57 +01:00
|
|
|
if (ret != 0)
|
2021-11-02 21:57:57 +01:00
|
|
|
break;
|
|
|
|
threadExit();
|
|
|
|
assert(0);
|
|
|
|
break;
|
2021-11-08 22:31:57 +01:00
|
|
|
}
|
2023-11-11 00:07:26 +01:00
|
|
|
case SYSCALL_ID_HELO:
|
|
|
|
ret = printf("HELLO FROM USERSPACE\n");
|
2021-11-02 21:57:57 +01:00
|
|
|
break;
|
2021-11-08 22:31:57 +01:00
|
|
|
case SYSCALL_ID_PUTC: {
|
2021-11-05 23:02:23 +01:00
|
|
|
unsigned int c;
|
|
|
|
ret = syscallGet1arg(userCtx, &c);
|
|
|
|
putc(c);
|
|
|
|
break;
|
2021-11-08 22:31:57 +01:00
|
|
|
}
|
2021-11-06 00:13:40 +01:00
|
|
|
case SYSCALL_ID_READ:
|
|
|
|
ret = keyboardRead();
|
|
|
|
break;
|
2021-11-08 23:22:03 +01:00
|
|
|
case SYSCALL_ID_TEST: {
|
|
|
|
unsigned int arg1, arg2, arg3, arg4, arg5;
|
|
|
|
ret = syscallGet5args(userCtx, &arg1, &arg2, &arg3, &arg4, &arg5);
|
|
|
|
printf("Got 5args from userspace %d %d %d %d %d\n", arg1, arg2, arg3, arg4, arg5);
|
|
|
|
break;
|
|
|
|
}
|
2024-02-13 00:19:39 +01:00
|
|
|
case SYSCALL_ID_BRK: {
|
2022-08-09 16:15:00 +02:00
|
|
|
|
|
|
|
struct uAddrSpace *as;
|
|
|
|
uaddr_t newHeapTop;
|
|
|
|
|
2024-02-13 00:19:39 +01:00
|
|
|
as = processGetAddrSpace(getCurrentThread()->process);
|
2022-08-09 16:15:00 +02:00
|
|
|
ret = syscallGet1arg(userCtx, (unsigned int *)&newHeapTop);
|
|
|
|
if (ret != 0)
|
|
|
|
break;
|
|
|
|
threadChangeCurrentContext(uAddrSpaceGetMMUContext(as));
|
2024-02-13 00:19:39 +01:00
|
|
|
// TODO : what if *newHeapTop raise page fault?
|
2022-08-09 16:15:00 +02:00
|
|
|
ret = sysBrk(as, newHeapTop);
|
|
|
|
threadChangeCurrentContext(NULL);
|
|
|
|
break;
|
|
|
|
}
|
2023-03-24 23:43:09 +01:00
|
|
|
case SYSCALL_ID_MMAP: {
|
|
|
|
struct uAddrSpace *as;
|
|
|
|
uaddr_t uaddr;
|
2024-02-04 21:42:29 +01:00
|
|
|
uaddr_t uaddr_ptr;
|
2023-03-24 23:43:09 +01:00
|
|
|
size_t size;
|
|
|
|
uint32_t rights;
|
|
|
|
uint32_t flags;
|
|
|
|
uaddr_t userPath;
|
|
|
|
|
|
|
|
char path[256];
|
|
|
|
|
|
|
|
as = processGetAddrSpace(getCurrentThread()->process);
|
2024-02-10 23:25:24 +01:00
|
|
|
ret = syscallGet5args(userCtx, (unsigned int *)&uaddr_ptr, (unsigned int *)&size,
|
|
|
|
(unsigned int *)&rights, (unsigned int *)&flags,
|
|
|
|
(unsigned int *)&userPath);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
break;
|
2024-02-04 21:42:29 +01:00
|
|
|
|
|
|
|
if (memcpyFromUser((vaddr_t)&uaddr, uaddr_ptr, sizeof(uaddr)) != sizeof(uaddr)) {
|
|
|
|
ret = -EFAULT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-03-24 23:43:09 +01:00
|
|
|
strzcpyFromUser((vaddr_t *)path, (uaddr_t *)userPath, sizeof(path));
|
2024-02-04 21:42:29 +01:00
|
|
|
|
|
|
|
printf("Trying mmap for device %s at %lu\n", path, (vaddr_t)uaddr);
|
2024-02-10 23:25:24 +01:00
|
|
|
if (strcmp(path, "/dev/zero") == 0) {
|
|
|
|
ret = zeroMmap(as, &uaddr, size, rights, flags);
|
2023-11-10 09:01:55 +01:00
|
|
|
}
|
2024-02-10 23:25:24 +01:00
|
|
|
if (!ret) {
|
|
|
|
if (memcpyToUser(uaddr_ptr, (vaddr_t)&uaddr, sizeof(uaddr)) != sizeof(uaddr)) {
|
2024-02-04 21:42:29 +01:00
|
|
|
ret = -EFAULT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2023-03-24 23:43:09 +01:00
|
|
|
break;
|
|
|
|
}
|
2024-02-10 23:25:24 +01:00
|
|
|
case SYSCALL_ID_MUNMAP: {
|
|
|
|
struct uAddrSpace *as;
|
|
|
|
uaddr_t uaddr;
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
ret = syscallGet2args(userCtx, (unsigned int *)&uaddr, (unsigned int *)&size);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
|
|
|
|
as = processGetAddrSpace(getCurrentThread()->process);
|
|
|
|
ret = uAddrSpaceUnmap(as, uaddr, size);
|
|
|
|
break;
|
|
|
|
}
|
2024-02-13 00:19:39 +01:00
|
|
|
case SYSCALL_ID_NEW_THREAD: {
|
|
|
|
struct uAddrSpace *as;
|
2024-02-14 23:20:46 +01:00
|
|
|
thread_id_t threadIdPtr;
|
|
|
|
thread_id_t threadId;
|
2024-02-13 00:19:39 +01:00
|
|
|
uaddr_t funcAddr;
|
|
|
|
uint32_t arg1, arg2;
|
|
|
|
size_t stackSize;
|
|
|
|
|
2024-02-14 23:20:46 +01:00
|
|
|
ret = syscallGet5args(userCtx, (unsigned int *)&threadIdPtr,
|
|
|
|
(unsigned int *)&funcAddr, (unsigned int *)&arg1,
|
2024-02-13 00:19:39 +01:00
|
|
|
(unsigned int *)&arg2, (unsigned int *)&stackSize);
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
if (stackSize <= 0) {
|
|
|
|
ret = -EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
2024-02-14 23:20:46 +01:00
|
|
|
if (memcpyFromUser((vaddr_t)&threadId, threadIdPtr, sizeof(threadId)) !=
|
|
|
|
sizeof(threadId)) {
|
|
|
|
ret = -EFAULT;
|
|
|
|
break;
|
|
|
|
}
|
2024-02-13 00:19:39 +01:00
|
|
|
|
|
|
|
as = processGetAddrSpace(getCurrentThread()->process);
|
|
|
|
stackSize = ALIGN(stackSize, PAGE_SIZE);
|
|
|
|
|
|
|
|
uaddr_t stackAddr = 0;
|
|
|
|
ret = zeroMmap(as, &stackAddr, stackSize, PAGING_MEM_READ | PAGING_MEM_WRITE, 0);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
|
|
|
|
struct thread *th = threadCreateUser(NULL, getCurrentThread()->process, funcAddr,
|
|
|
|
arg1, arg2, stackAddr + stackSize);
|
|
|
|
|
|
|
|
if (th == NULL) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
uAddrSpaceUnmap(as, stackAddr, stackSize);
|
|
|
|
}
|
2024-02-14 23:20:46 +01:00
|
|
|
threadId = threadGetId(th);
|
|
|
|
|
|
|
|
if (memcpyToUser(threadIdPtr, (vaddr_t)&threadId, sizeof(threadId)) !=
|
|
|
|
sizeof(threadId)) {
|
|
|
|
ret = -EFAULT;
|
|
|
|
break;
|
|
|
|
}
|
2024-02-13 00:19:39 +01:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2024-02-14 18:43:47 +01:00
|
|
|
case SYSCALL_ID_USLEEP: {
|
|
|
|
unsigned int sleep;
|
|
|
|
|
|
|
|
ret = syscallGet1arg(userCtx, &sleep);
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
|
|
|
|
ret = threadUsleep(sleep);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2024-02-14 23:20:46 +01:00
|
|
|
case SYSCALL_ID_GETPID: {
|
2024-02-16 00:40:48 +01:00
|
|
|
ret = processGetId(getCurrentThread()->process);
|
2024-02-14 23:20:46 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SYSCALL_ID_GETTID: {
|
2024-02-16 00:40:48 +01:00
|
|
|
ret = threadGetId(getCurrentThread());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SYSCALL_ID_THREAD_JOIN: {
|
|
|
|
thread_id_t tid;
|
|
|
|
|
|
|
|
ret = syscallGet1arg(userCtx, (unsigned int *)&tid);
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
ret = processJoinThread(getCurrentThread()->process, tid);
|
2024-02-14 23:20:46 +01:00
|
|
|
break;
|
|
|
|
}
|
2021-11-02 21:57:57 +01:00
|
|
|
default:
|
2021-11-08 22:31:57 +01:00
|
|
|
printf("Unknon syscall id %d\n", syscallId);
|
|
|
|
ret = -ENOENT;
|
2021-11-02 21:57:57 +01:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|