#include "syscall.h" #include "kernel.h" #include "keyboard.h" #include "klibc.h" #include "paging.h" #include "process.h" #include "stdarg.h" #include "thread.h" #include "types.h" #include "uaccess.h" #include "uaddrspace.h" #include "zero.h" int syscallExecute(int syscallId, const struct cpu_state *userCtx) { int ret = 0; switch (syscallId) { case SYSCALL_ID_EXIT: { uint status; ret = syscallGet1arg(userCtx, &status); if (ret != 0) break; threadExit(); assert(0); break; } case SYSCALL_ID_HELO: ret = printf("HELLO FROM USERSPACE\n"); break; case SYSCALL_ID_PUTC: { unsigned int c; ret = syscallGet1arg(userCtx, &c); putc(c); break; } case SYSCALL_ID_READ: ret = keyboardRead(); break; 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; } case SYSCALL_ID_BRK: { struct uAddrSpace *as; uaddr_t newHeapTop; as = processGetAddrSpace(getCurrentThread()->process); ret = syscallGet1arg(userCtx, (unsigned int *)&newHeapTop); if (ret != 0) break; threadChangeCurrentContext(uAddrSpaceGetMMUContext(as)); // TODO : what if *newHeapTop raise page fault? ret = sysBrk(as, newHeapTop); threadChangeCurrentContext(NULL); break; } case SYSCALL_ID_MMAP: { struct uAddrSpace *as; uaddr_t uaddr; uaddr_t uaddr_ptr; size_t size; uint32_t rights; uint32_t flags; uaddr_t userPath; char path[256]; as = processGetAddrSpace(getCurrentThread()->process); ret = syscallGet5args(userCtx, (unsigned int *)&uaddr_ptr, (unsigned int *)&size, (unsigned int *)&rights, (unsigned int *)&flags, (unsigned int *)&userPath); if (ret) break; if (memcpyFromUser((vaddr_t)&uaddr, uaddr_ptr, sizeof(uaddr)) != sizeof(uaddr)) { ret = -EFAULT; break; } strzcpyFromUser((vaddr_t *)path, (uaddr_t *)userPath, sizeof(path)); printf("Trying mmap for device %s at %lu\n", path, (vaddr_t)uaddr); if (strcmp(path, "/dev/zero") == 0) { ret = zeroMmap(as, &uaddr, size, rights, flags); } if (!ret) { if (memcpyToUser(uaddr_ptr, (vaddr_t)&uaddr, sizeof(uaddr)) != sizeof(uaddr)) { ret = -EFAULT; break; } } break; } 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; } case SYSCALL_ID_NEW_THREAD: { struct uAddrSpace *as; thread_id_t threadIdPtr; thread_id_t threadId; uaddr_t funcAddr; uint32_t arg1, arg2; size_t stackSize; ret = syscallGet5args(userCtx, (unsigned int *)&threadIdPtr, (unsigned int *)&funcAddr, (unsigned int *)&arg1, (unsigned int *)&arg2, (unsigned int *)&stackSize); if (ret) break; if (stackSize <= 0) { ret = -EINVAL; break; } if (memcpyFromUser((vaddr_t)&threadId, threadIdPtr, sizeof(threadId)) != sizeof(threadId)) { ret = -EFAULT; break; } 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); } threadId = threadGetId(th); if (memcpyToUser(threadIdPtr, (vaddr_t)&threadId, sizeof(threadId)) != sizeof(threadId)) { ret = -EFAULT; break; } break; } case SYSCALL_ID_USLEEP: { unsigned int sleep; ret = syscallGet1arg(userCtx, &sleep); if (ret) break; ret = threadUsleep(sleep); break; } case SYSCALL_ID_GETPID: { ret = processGetId(getCurrentThread()->process); break; } case SYSCALL_ID_GETTID: { 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); break; } default: printf("Unknon syscall id %d\n", syscallId); ret = -ENOENT; } return ret; }