Browse Source

feat(syscall): add set_thread_area

greatbridf 1 year ago
parent
commit
3cf21d6082

+ 2 - 0
CMakeLists.txt

@@ -50,6 +50,7 @@ set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
                         src/kernel/hw/serial.cpp
                         src/kernel/hw/timer.c
                         src/kernel/event/event.cpp
+                        src/kernel/user/thread_local.cc
                         src/kernel/signal.cpp
                         src/types/elf.cpp
                         src/types/libstdcpp.cpp
@@ -75,6 +76,7 @@ set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
                         include/kernel/hw/timer.h
                         include/kernel/input/keycodes.h
                         include/kernel/input/input_event.h
+                        include/kernel/user/thread_local.hpp
                         include/types/bitmap.hpp
                         include/types/buffer.hpp
                         include/types/elf.hpp

+ 8 - 8
gblibc/private-include/syscall.h

@@ -43,40 +43,40 @@ static inline uint32_t syscall0(uint32_t no)
 static inline uint32_t syscall1(uint32_t no, uint32_t arg)
 {
     asm volatile(
-        "movl %1, %%edi\n"
+        "movl %1, %%ebx\n"
         "movl %2, %%eax\n"
         "int $0x80\n"
         "movl %%eax, %0"
         : "=g"(no)
         : "g"(arg), "g"(no)
-        : "eax", "edi");
+        : "eax", "ebx");
     return no;
 }
 static inline uint32_t syscall2(uint32_t no, uint32_t arg1, uint32_t arg2)
 {
     asm volatile(
-        "movl %1, %%edi\n"
-        "movl %2, %%esi\n"
+        "movl %1, %%ebx\n"
+        "movl %2, %%ecx\n"
         "movl %3, %%eax\n"
         "int $0x80\n"
         "movl %%eax, %0"
         : "=g"(no)
         : "g"(arg1), "g"(arg2), "g"(no)
-        : "eax", "edi", "esi");
+        : "eax", "ebx", "ecx");
     return no;
 }
 static inline uint32_t syscall3(uint32_t no, uint32_t arg1, uint32_t arg2, uint32_t arg3)
 {
     asm volatile(
-        "movl %1, %%edi\n"
-        "movl %2, %%esi\n"
+        "movl %1, %%ebx\n"
+        "movl %2, %%ecx\n"
         "movl %3, %%edx\n"
         "movl %4, %%eax\n"
         "int $0x80\n"
         "movl %%eax, %0"
         : "=g"(no)
         : "g"(arg1), "g"(arg2), "g"(arg3), "g"(no)
-        : "eax", "edx", "edi", "esi");
+        : "eax", "ebx", "ecx", "edx");
     return no;
 }
 

+ 1 - 1
include/kernel/mem.h

@@ -127,7 +127,7 @@ typedef struct segment_descriptor_struct {
 } segment_descriptor;
 
 // in mem.cpp
-extern segment_descriptor gdt[6];
+extern segment_descriptor gdt[7];
 
 void create_segment_descriptor(
     segment_descriptor* sd,

+ 21 - 0
include/kernel/user/thread_local.hpp

@@ -0,0 +1,21 @@
+#pragma once
+
+#include <stdint.h>
+
+namespace kernel::user {
+
+struct user_desc {
+    uint32_t entry_number;
+    uint32_t base_addr;
+    uint32_t limit;
+    uint32_t seg_32bit : 1;
+    uint32_t contents : 2;
+    uint32_t read_exec_only : 1;
+    uint32_t limit_in_pages : 1;
+    uint32_t seg_not_present : 1;
+    uint32_t useable : 1;
+};
+
+int set_thread_area(user_desc* ptr);
+
+} // namespace kernel::user

+ 1 - 1
src/kernel/mem.cpp

@@ -29,7 +29,7 @@ static types::bitmap mem_bitmap(
     1024 * 1024);
 
 // global
-segment_descriptor gdt[6];
+segment_descriptor gdt[7];
 
 uint8_t e820_mem_map[1024];
 uint32_t e820_mem_map_count;

+ 55 - 35
src/kernel/syscall.cpp

@@ -2,6 +2,7 @@
 #include <asm/sys.h>
 #include <assert.h>
 #include <bits/ioctl.h>
+#include <kernel/user/thread_local.hpp>
 #include <kernel/errno.h>
 #include <kernel/interrupt.h>
 #include <kernel/log.hpp>
@@ -19,7 +20,17 @@
 #include <types/lock.hpp>
 #include <types/status.h>
 
-#define SYSCALL_HANDLERS_SIZE (128)
+#define SYSCALL_NO ((data)->s_regs.eax)
+#define SYSCALL_RETVAL ((data)->s_regs.eax)
+
+#define SYSCALL_ARG1(type, name) type name = (type)((data)->s_regs.ebx)
+#define SYSCALL_ARG2(type, name) type name = (type)((data)->s_regs.ecx)
+#define SYSCALL_ARG3(type, name) type name = (type)((data)->s_regs.edx)
+#define SYSCALL_ARG4(type, name) type name = (type)((data)->s_regs.esi)
+#define SYSCALL_ARG5(type, name) type name = (type)((data)->s_regs.edi)
+#define SYSCALL_ARG6(type, name) type name = (type)((data)->s_regs.ebp)
+
+#define SYSCALL_HANDLERS_SIZE (385)
 syscall_handler syscall_handlers[SYSCALL_HANDLERS_SIZE];
 
 extern "C" void _syscall_stub_fork_return(void);
@@ -69,9 +80,9 @@ int _syscall_fork(interrupt_stack* data)
 
 int _syscall_write(interrupt_stack* data)
 {
-    int fd = data->s_regs.edi;
-    const char* buf = reinterpret_cast<const char*>(data->s_regs.esi);
-    size_t n = data->s_regs.edx;
+    SYSCALL_ARG1(int, fd);
+    SYSCALL_ARG2(const char*, buf);
+    SYSCALL_ARG3(size_t, n);
 
     auto* file = current_process->files[fd];
 
@@ -102,9 +113,9 @@ int _syscall_write(interrupt_stack* data)
 
 int _syscall_read(interrupt_stack* data)
 {
-    int fd = data->s_regs.edi;
-    char* buf = reinterpret_cast<char*>(data->s_regs.esi);
-    size_t n = data->s_regs.edx;
+    SYSCALL_ARG1(int, fd);
+    SYSCALL_ARG2(char*, buf);
+    SYSCALL_ARG3(size_t, n);
 
     auto* file = current_process->files[fd];
 
@@ -146,7 +157,8 @@ int _syscall_sleep(interrupt_stack*)
 
 int _syscall_chdir(interrupt_stack* data)
 {
-    const char* path = reinterpret_cast<const char*>(data->s_regs.edi);
+    SYSCALL_ARG1(const char*, path);
+
     auto* dir = fs::vfs_open(*current_process->root,
         current_process->pwd.c_str(), path);
     if (!dir)
@@ -167,9 +179,9 @@ int _syscall_chdir(interrupt_stack* data)
 // @param envp: environment variables end with nullptr
 int _syscall_execve(interrupt_stack* data)
 {
-    const char* exec = reinterpret_cast<const char*>(data->s_regs.edi);
-    char* const* argv = reinterpret_cast<char* const*>(data->s_regs.esi);
-    char* const* envp = reinterpret_cast<char* const*>(data->s_regs.edx);
+    SYSCALL_ARG1(const char*, exec);
+    SYSCALL_ARG2(char* const*, argv);
+    SYSCALL_ARG3(char* const*, envp);
 
     types::elf::elf32_load_data d;
     d.argv = argv;
@@ -195,7 +207,7 @@ int _syscall_execve(interrupt_stack* data)
 // @param exit_code
 int NORETURN _syscall_exit(interrupt_stack* data)
 {
-    uint32_t exit_code = data->s_regs.edi;
+    SYSCALL_ARG1(int, exit_code);
 
     // TODO: terminating a thread only
     if (current_process->thds.size() != 1)
@@ -212,7 +224,7 @@ int NORETURN _syscall_exit(interrupt_stack* data)
 // @return pid of the exited process
 int _syscall_wait(interrupt_stack* data)
 {
-    auto* arg1 = reinterpret_cast<int*>(data->s_regs.edi);
+    SYSCALL_ARG1(int*, arg1);
 
     auto& cv = current_process->cv_wait;
     auto& mtx = cv.mtx();
@@ -245,9 +257,9 @@ int _syscall_wait(interrupt_stack* data)
 
 int _syscall_getdents(interrupt_stack* data)
 {
-    int fd = data->s_regs.edi;
-    auto* buf = (char*)(data->s_regs.esi);
-    size_t cnt = data->s_regs.edx;
+    SYSCALL_ARG1(int, fd);
+    SYSCALL_ARG2(char*, buf);
+    SYSCALL_ARG3(size_t, cnt);
 
     auto* dir = current_process->files[fd];
     if (dir->type != fs::file::types::ind || !dir->ptr.ind->flags.in.directory)
@@ -286,16 +298,17 @@ int _syscall_getdents(interrupt_stack* data)
 
 int _syscall_open(interrupt_stack* data)
 {
-    auto* path = (const char*)data->s_regs.edi;
-    uint32_t flags = data->s_regs.esi;
+    SYSCALL_ARG1(const char*, path);
+    SYSCALL_ARG2(uint32_t, flags);
+
     return current_process->files.open(
         *current_process, path, flags);
 }
 
 int _syscall_getcwd(interrupt_stack* data)
 {
-    char* buf = reinterpret_cast<char*>(data->s_regs.edi);
-    size_t bufsize = reinterpret_cast<size_t>(data->s_regs.esi);
+    SYSCALL_ARG1(char*, buf);
+    SYSCALL_ARG2(size_t, bufsize);
 
     // TODO: use copy_to_user
     strncpy(buf, current_process->pwd.c_str(), bufsize);
@@ -321,7 +334,7 @@ int _syscall_setsid(interrupt_stack*)
 
 int _syscall_getsid(interrupt_stack* data)
 {
-    pid_t pid = data->s_regs.edi;
+    SYSCALL_ARG1(pid_t, pid);
 
     if (!procs->try_find(pid))
         return -ESRCH;
@@ -334,34 +347,34 @@ int _syscall_getsid(interrupt_stack* data)
 
 int _syscall_close(interrupt_stack* data)
 {
-    int fd = data->s_regs.edi;
+    SYSCALL_ARG1(int, fd);
     current_process->files.close(fd);
     return 0;
 }
 
 int _syscall_dup(interrupt_stack* data)
 {
-    int old_fd = data->s_regs.edi;
+    SYSCALL_ARG1(int, old_fd);
     return current_process->files.dup(old_fd);
 }
 
 int _syscall_dup2(interrupt_stack* data)
 {
-    int old_fd = data->s_regs.edi;
-    int new_fd = data->s_regs.esi;
+    SYSCALL_ARG1(int, old_fd);
+    SYSCALL_ARG2(int, new_fd);
     return current_process->files.dup2(old_fd, new_fd);
 }
 
 int _syscall_pipe(interrupt_stack* data)
 {
-    auto& pipefd = *(int(*)[2])data->s_regs.edi;
+    SYSCALL_ARG1(int*, pipefd);
     return current_process->files.pipe(pipefd);
 }
 
 int _syscall_setpgid(interrupt_stack* data)
 {
-    pid_t pid = data->s_regs.edi;
-    pid_t pgid = data->s_regs.esi;
+    SYSCALL_ARG1(pid_t, pid);
+    SYSCALL_ARG2(pid_t, pgid);
 
     if (pgid < 0)
         return -EINVAL;
@@ -387,8 +400,8 @@ int _syscall_setpgid(interrupt_stack* data)
 
 int _syscall_ioctl(interrupt_stack* data)
 {
-    int fd = data->s_regs.edi;
-    unsigned long request = data->s_regs.esi;
+    SYSCALL_ARG1(int, fd);
+    SYSCALL_ARG2(unsigned long, request);
 
     // TODO: check fd type and get tty* from fd
     //
@@ -402,7 +415,7 @@ int _syscall_ioctl(interrupt_stack* data)
 
     switch (request) {
     case TIOCGPGRP: {
-        auto* pgid = (pid_t*)data->s_regs.edx;
+        SYSCALL_ARG3(pid_t*, pgid);
         tty* ctrl_tty = current_process->control_tty;
         // TODO: copy_to_user
         *pgid = ctrl_tty->get_pgrp();
@@ -410,9 +423,9 @@ int _syscall_ioctl(interrupt_stack* data)
     }
     case TIOCSPGRP: {
         // TODO: copy_from_user
-        pid_t pgid = *(const pid_t*)data->s_regs.edx;
+        SYSCALL_ARG3(const pid_t*, pgid);
         tty* ctrl_tty = current_process->control_tty;
-        ctrl_tty->set_pgrp(pgid);
+        ctrl_tty->set_pgrp(*pgid);
         break;
     }
     default:
@@ -432,15 +445,21 @@ int _syscall_getppid(interrupt_stack*)
     return current_process->ppid;
 }
 
+int _syscall_set_thread_area(interrupt_stack* data)
+{
+    SYSCALL_ARG1(kernel::user::user_desc*, ptr);
+    return kernel::user::set_thread_area(ptr);
+}
+
 extern "C" void syscall_entry(interrupt_stack* data)
 {
-    int syscall_no = data->s_regs.eax;
+    int syscall_no = SYSCALL_NO;
     if (syscall_no >= SYSCALL_HANDLERS_SIZE)
         kill_current(-1);
 
     int ret = syscall_handlers[syscall_no](data);
 
-    data->s_regs.eax = ret;
+    SYSCALL_RETVAL = ret;
 
     check_signal();
 }
@@ -471,4 +490,5 @@ void init_syscall(void)
     syscall_handlers[110] = _syscall_getppid;
     syscall_handlers[112] = _syscall_setsid;
     syscall_handlers[124] = _syscall_getsid;
+    syscall_handlers[243] = _syscall_set_thread_area;
 }

+ 35 - 0
src/kernel/user/thread_local.cc

@@ -0,0 +1,35 @@
+#include <kernel/mem.h>
+#include <kernel/user/thread_local.hpp>
+
+#include <string.h>
+#include <cstddef>
+
+namespace kernel::user {
+
+int set_thread_area(user_desc* ptr)
+{
+    if (ptr->read_exec_only && ptr->seg_not_present) {
+        void* dst = (void*)ptr->base_addr;
+        std::size_t len = ptr->limit;
+        if (len > 0 && dst)
+            memset(dst, 0x00, len);
+        return 0;
+    }
+
+    if (ptr->entry_number == -1U)
+        ptr->entry_number = 6;
+    else
+        return -1;
+
+    gdt[6].limit_low = ptr->limit & 0xFFFF;
+    gdt[6].base_low = ptr->base_addr & 0xFFFF;
+    gdt[6].base_mid = (ptr->base_addr >> 16) & 0xFF;
+    gdt[6].access = SD_TYPE_DATA_USER;
+    gdt[6].limit_high = (ptr->limit >> 16) & 0xF;
+    gdt[6].flags = (ptr->limit_in_pages << 3) | (ptr->seg_32bit << 2);
+    gdt[6].base_high = (ptr->base_addr >> 24) & 0xFF;
+
+    return 0;
+}
+
+} // namespace kernel::user

+ 2 - 1
src/kinit.cpp

@@ -45,8 +45,9 @@ static inline void load_new_gdt(void)
     create_segment_descriptor(gdt + 3, 0, ~0, 0b1100, SD_TYPE_CODE_USER);
     create_segment_descriptor(gdt + 4, 0, ~0, 0b1100, SD_TYPE_DATA_USER);
     create_segment_descriptor(gdt + 5, (uint32_t)&tss, sizeof(tss), 0b0000, SD_TYPE_TSS);
+    create_segment_descriptor(gdt + 6, 0, 0, 0b1100, SD_TYPE_DATA_USER);
 
-    asm_load_gdt((6 * 8 - 1) << 16, (pptr_t)gdt);
+    asm_load_gdt((7 * 8 - 1) << 16, (pptr_t)gdt);
     asm_load_tr((6 - 1) * 8);
 
     asm_cli();