Эх сурвалжийг харах

Merge branch 'master' into libc

greatbridf 2 жил өмнө
parent
commit
9ada56e74b

+ 2 - 0
CMakeLists.txt

@@ -9,6 +9,7 @@ set(CMAKE_CXX_LINK_EXECUTABLE
 set(CMAKE_ASM_FLAGS "-m32")
 set(CMAKE_C_FLAGS "-nostdinc -m32 -nostdlib -W -Wall -Wextra -Wno-builtin-declaration-mismatch -Wno-format -Werror=implicit-int -Werror=implicit-function-declaration -Werror=strict-aliasing -fverbose-asm -fno-exceptions -fno-pic -ffreestanding -mstack-protector-guard=global")
 set(CMAKE_CXX_FLAGS "-nostdinc -m32 -nostdlib -W -Wall -Wextra -Wno-builtin-declaration-mismatch -Wno-format -fverbose-asm -fno-use-cxa-atexit -fno-exceptions -fno-pic -ffreestanding -fno-rtti -mstack-protector-guard=global")
+set(CMAKE_CXX_LINK_FLAGS "")
 set(CMAKE_CXX_STANDARD 20)
 
 if (CMAKE_BUILD_TYPE STREQUAL "Debug")
@@ -126,6 +127,7 @@ add_custom_target(boot.img
     COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/stack-test.out ::stack.out
     COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/init.out ::init.elf
     COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/sh.out ::sh.elf
+    COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/priv-test.out ::priv.elf
 )
 
 add_custom_command(OUTPUT run

+ 1 - 1
gblibc/include/sys/types.h

@@ -7,7 +7,7 @@
 extern "C" {
 #endif
 
-typedef ssize_t pid_t;
+typedef int pid_t;
 
 #ifdef __cplusplus
 }

+ 8 - 1
include/kernel/mm.hpp

@@ -183,7 +183,7 @@ public:
             }
 
             this->unmap(iter);
-            // TODO: handle memory leak
+
             iter = m_areas.erase(iter);
         }
     }
@@ -214,6 +214,12 @@ public:
     constexpr void unmap(iterator_type area)
     {
         int i = 0;
+
+        // TODO: 
+        // if there are more than 4 pages, calling invlpg
+        // should be faster. otherwise, we use movl cr3
+        // bool should_invlpg = (area->pgs->size() > 4);
+
         for (auto& pg : *area->pgs) {
             if (*pg.ref_count == 1) {
                 ki_free(pg.ref_count);
@@ -228,6 +234,7 @@ public:
 
             invalidate_tlb((uint32_t)area->start + (i++) * PAGE_SIZE);
         }
+        types::pdelete<types::kernel_ident_allocator>(area->pgs);
         area->attr.v = 0;
         area->start = 0;
     }

+ 35 - 29
include/kernel/process.hpp

@@ -149,17 +149,34 @@ public:
     class filearr {
     public:
         using container_type = types::list<fs::file>;
-        using array_type = types::hash_map<int, container_type::iterator_type, types::linux_hasher<size_t>>;
+        using array_type = types::map<int, container_type::iterator_type>;
 
     private:
-        inline static container_type* files = nullptr;
+        inline static container_type* files;
         array_type arr;
         int next_fd = 0;
 
+    public:
+        inline static void init_global_file_container(void)
+        {
+            files = types::pnew<types::kernel_allocator>(files);
+        }
+
+    private:
+        // iter should not be nullptr
+        constexpr void _close(container_type::iterator_type iter)
+        {
+            if (iter->ref == 1)
+                files->erase(iter);
+            else
+                --iter->ref;
+        }
+
     public:
         constexpr filearr(const filearr&) = delete;
         constexpr filearr& operator=(const filearr&) = delete;
         constexpr filearr& operator=(filearr&&) = delete;
+        constexpr filearr(void) = default;
         constexpr filearr(filearr&& val)
             : arr { types::move(val.arr) }
             , next_fd { val.next_fd }
@@ -167,12 +184,6 @@ public:
             val.next_fd = 0;
         }
 
-        explicit filearr()
-        {
-            if (!files)
-                files = types::pnew<types::kernel_allocator>(files);
-        }
-
         constexpr void dup(const filearr& orig)
         {
             if (this->next_fd)
@@ -180,13 +191,9 @@ public:
 
             this->next_fd = orig.next_fd;
 
-            for (int i = 0; i < this->next_fd; ++i) {
-                auto iter = orig.arr.find(i);
-                if (!iter)
-                    continue;
-
-                this->arr.emplace(iter->key, iter->value);
-                ++iter->value->ref;
+            for (auto iter : orig.arr) {
+                this->arr.insert(types::make_pair(iter.key, iter.value));
+                ++iter.value->ref;
             }
         }
 
@@ -230,31 +237,28 @@ public:
                 1 });
 
             int fd = next_fd++;
-            arr.emplace(fd, iter);
+            arr.insert(types::make_pair(fd, iter));
             return fd;
         }
 
-        // close file descriptor
-        // where iter is guaranteed not nullptr
-        constexpr void close(array_type::iterator_type iter)
+        constexpr void close(int fd)
         {
-            if (iter->value->ref == 1)
-                files->erase(iter->value);
-            else
-                --iter->value->ref;
+            auto iter = arr.find(fd);
+            if (iter) {
+                _close(iter->value);
+                arr.erase(iter);
+            }
         }
 
-        constexpr void close(int fd)
+        constexpr void close_all(void)
         {
-            auto iter = arr.find(fd);
-            if (iter)
-                close(iter);
+            for (auto iter : this->arr)
+                close(iter.key);
         }
 
         constexpr ~filearr()
         {
-            for (int i = 0; i < next_fd; ++i)
-                close(i);
+            close_all();
         }
     };
 
@@ -360,6 +364,8 @@ public:
             m_child_idx.remove(children);
         }
     }
+
+    void kill(pid_t pid, int exit_code);
 };
 
 class readyqueue final {

+ 5 - 3
include/types/map.hpp

@@ -386,7 +386,7 @@ public:
             return ret;
         }
 
-        constexpr operator bool(void)
+        explicit constexpr operator bool(void)
         {
             return p;
         }
@@ -575,8 +575,10 @@ private:
                 }
             } else {
                 s->tored();
-                p->toblack();
-                this->_erase(p);
+                if (node::is_black(p))
+                    this->_erase(p);
+                else
+                    p->toblack();
             }
         }
     }

+ 28 - 2
src/kernel/interrupt.cpp

@@ -21,6 +21,14 @@
 
 static struct IDT_entry IDT[256];
 
+static inline void NORETURN _halt_forever(void)
+{
+    asm_cli();
+    asm_hlt();
+    for (;;)
+        ;
+}
+
 void init_idt()
 {
     asm_cli();
@@ -159,6 +167,16 @@ static inline void _int14_panic(void* eip, void* cr2, struct page_fault_error_co
     assert(false);
 }
 
+static inline void NORETURN _int14_kill_user(void)
+{
+    char buf[256] {};
+    snprintf(buf, 256, "Segmentation Fault (pid%d killed)\n", current_process->pid);
+    kmsg(buf);
+    procs->kill(current_process->pid, -1);
+    schedule();
+    _halt_forever();
+}
+
 // page fault
 extern "C" void int14_handler(int14_data* d)
 {
@@ -169,8 +187,16 @@ extern "C" void int14_handler(int14_data* d)
         mms = kernel_mms;
 
     auto mm_area = mms->find(d->l_addr);
-    if (unlikely(mm_area == mms->end()))
-        _int14_panic(d->v_eip, d->l_addr, d->error_code);
+    if (unlikely(mm_area == mms->end())) {
+        if (d->error_code.user) {
+            // user access of address that does not exist
+            _int14_kill_user();
+        } else {
+            _int14_panic(d->v_eip, d->l_addr, d->error_code);
+        }
+    }
+    if (unlikely(d->error_code.user && mm_area->attr.in.system))
+        _int14_kill_user();
 
     pte_t* pte = to_pte(mms->m_pd, d->l_addr);
     page* page = lto_page(&mm_area, d->l_addr);

+ 38 - 0
src/kernel/process.cpp

@@ -84,6 +84,42 @@ process::process(pid_t _ppid, bool _system)
 {
 }
 
+void proclist::kill(pid_t pid, int exit_code)
+{
+    process* proc = this->find(pid);
+
+    // remove threads from ready list
+    for (auto& thd : proc->thds.underlying_list()) {
+        thd.attr.ready = 0;
+        readythds->remove_all(&thd);
+    }
+
+    // write back mmap'ped files and close them
+    proc->files.close_all();
+
+    // unmap all user memory areas
+    proc->mms.clear_user();
+
+    // init should never exit
+    if (proc->ppid == 0) {
+        console->print("kernel panic: init exited!\n");
+        crash();
+    }
+
+    // make child processes orphans (children of init)
+    this->make_children_orphans(pid);
+
+    proc->attr.zombie = 1;
+
+    // notify parent process and init
+    auto* parent = this->find(proc->ppid);
+    auto* init = this->find(1);
+    while (!proc->wait_lst.empty()) {
+        init->wait_lst.push(proc->wait_lst.front());
+    }
+    parent->wait_lst.push({ nullptr, (void*)pid, (void*)exit_code, nullptr });
+}
+
 inline void NORETURN _noreturn_crash(void)
 {
     for (;;)
@@ -210,6 +246,8 @@ void NORETURN init_scheduler(void)
     procs = types::pnew<types::kernel_allocator>(procs);
     readythds = types::pnew<types::kernel_allocator>(readythds);
 
+    process::filearr::init_global_file_container();
+
     // init process has no parent
     auto* init = &procs->emplace(0)->value;
     init->files.open("/dev/console", 0);

+ 1 - 33
src/kernel/syscall.cpp

@@ -159,8 +159,6 @@ void _syscall_exec(interrupt_stack* data)
 void _syscall_exit(interrupt_stack* data)
 {
     uint32_t exit_code = data->s_regs.edi;
-    pid_t pid = current_process->pid;
-    pid_t ppid = current_process->ppid;
 
     // TODO: terminating a thread only
     if (current_thread->owner->thds.size() != 1) {
@@ -168,37 +166,7 @@ void _syscall_exit(interrupt_stack* data)
     }
 
     // terminating a whole process:
-
-    // remove threads from ready list
-    for (auto& thd : current_process->thds.underlying_list()) {
-        thd.attr.ready = 0;
-        readythds->remove_all(&thd);
-    }
-
-    // TODO: write back mmap'ped files and close them
-
-    // unmap all user memory areas
-    current_process->mms.clear_user();
-
-    // init should never exit
-    if (current_process->ppid == 0) {
-        console->print("kernel panic: init exited!\n");
-        crash();
-    }
-
-    // make child processes orphans (children of init)
-    procs->make_children_orphans(pid);
-
-    current_process->attr.zombie = 1;
-
-    // notify parent process and init
-    auto* proc = procs->find(pid);
-    auto* parent = procs->find(ppid);
-    auto* init = procs->find(1);
-    while (!proc->wait_lst.empty()) {
-        init->wait_lst.push(proc->wait_lst.front());
-    }
-    parent->wait_lst.push({ current_thread, (void*)pid, (void*)exit_code, nullptr });
+    procs->kill(current_process->pid, exit_code);
 
     // switch to new process and continue
     schedule();

+ 3 - 2
user-space-program/CMakeLists.txt

@@ -5,7 +5,7 @@ set(CMAKE_C_FLAGS "-nostdinc -nostdlib -static -m32 -W -Wall -Wextra -Werror -ms
 set(CMAKE_ASM_FLAGS "-m32 -static -mstack-protector-guard=global -g0")
 
 link_libraries(gblibc)
-add_link_options(-nostdlib -Ttext 0x40000000 -T ${CMAKE_CURRENT_SOURCE_DIR}/script.ld)
+add_link_options(-nostdlib -T ${CMAKE_CURRENT_SOURCE_DIR}/script.ld)
 # set(LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/script.ld)
 
 set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "")
@@ -16,7 +16,8 @@ add_executable(interrupt-test.out interrupt-test.s)
 add_executable(stack-test.out stack-test.s)
 add_executable(init.out init.c)
 add_executable(sh.out sh.c)
+add_executable(priv-test.out priv-test.c)
 
 add_custom_target(user_space_programs
-    DEPENDS hello-world.out interrupt-test.out stack-test.out init.out sh.out
+    DEPENDS hello-world.out interrupt-test.out stack-test.out init.out sh.out priv-test.out
 )

+ 5 - 0
user-space-program/priv-test.c

@@ -0,0 +1,5 @@
+int main(void) {
+    int* ptr = (int*)0x10000;
+    *ptr = 0x114514;
+    return -1;
+}

+ 1 - 1
user-space-program/script.ld

@@ -11,7 +11,7 @@ MEMORY
 
 SECTIONS
 {
-    .text :
+    .text 0x40000000 :
     {
         *(.text)
         *(.text*)