Преглед на файлове

Merge branch 'master' into shell

greatbridf преди 2 години
родител
ревизия
5808eb0276
променени са 7 файла, в които са добавени 113 реда и са изтрити 43 реда
  1. 40 1
      include/kernel/mm.hpp
  2. 13 11
      include/types/buffer.hpp
  3. 3 9
      include/types/string.hpp
  4. 3 2
      include/types/vector.hpp
  5. 13 2
      src/kernel/interrupt.cpp
  6. 11 7
      src/kernel/mem.cpp
  7. 30 11
      src/types/elf.cpp

+ 40 - 1
include/kernel/mm.hpp

@@ -2,6 +2,7 @@
 
 #include <kernel/mem.h>
 #include <kernel/vfs.hpp>
+#include <stdint.h>
 #include <types/allocator.hpp>
 #include <types/cplusplus.hpp>
 #include <types/list.hpp>
@@ -34,6 +35,7 @@ struct page {
 // TODO: shared mapping
 // @param len is aligned to 4kb boundary automatically, exceeding part will
 // be filled with '0's and not written back to the file
+// @param offset MUST be aligned to 4kb
 int mmap(
     void* hint,
     size_t len,
@@ -60,6 +62,30 @@ namespace kernel {
 class mm_list;
 } // namespace kernel
 
+template <uint32_t base, uint32_t expo>
+inline constexpr uint32_t pow()
+{
+    if constexpr (expo == 0)
+        return 1;
+    if constexpr (expo == 1)
+        return base;
+    if constexpr (expo % 2 == 0)
+        return pow<base, expo / 2>() * pow<base, expo / 2>();
+    else
+        return pow<base, expo / 2>() * pow<base, expo / 2 + 1>();
+}
+
+template <int n>
+inline constexpr uint32_t align_down(uint32_t v)
+{
+    return v & ~(pow<2, n>() - 1);
+}
+template <int n>
+inline constexpr uint32_t align_up(uint32_t v)
+{
+    return align_down<n>(v + pow<2, n>() - 1);
+}
+
 struct mm {
 public:
     void* start;
@@ -215,7 +241,7 @@ public:
     {
         int i = 0;
 
-        // TODO: 
+        // 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);
@@ -247,6 +273,19 @@ public:
 
         return this->end();
     }
+
+    bool is_avail(void* start, size_t len)
+    {
+        start = (void*)align_down<12>((uint32_t)start);
+        len = align_up<12>((uint32_t)start + len)
+            - (uint32_t)start;
+        for (const auto& area : *this) {
+            if (!area.is_avail(start, (char*)start + len))
+                return false;
+        }
+
+        return true;
+    }
 };
 
 } // namespace kernel

+ 13 - 11
include/types/buffer.hpp

@@ -1,6 +1,7 @@
 #pragma once
 
 #include <stdint.h>
+#include <stdio.h>
 #include <types/allocator.hpp>
 
 namespace types {
@@ -90,43 +91,44 @@ public:
         return count == static_cast<size_t>(end - start + 1);
     }
 
-    constexpr char front(void)
+    constexpr int front(void)
     {
+        if (empty())
+            return EOF;
         return *base;
     }
 
-    constexpr char back(void)
+    constexpr int back(void)
     {
+        if (empty())
+            return EOF;
         return *_backward(head);
     }
 
-    constexpr char get(void)
+    constexpr int get(void)
     {
-        // TODO: set error flag
         if (empty())
-            return 0xff;
+            return EOF;
 
         char c = _get_char(base);
         base = _forward(base);
         return c;
     }
 
-    constexpr char pop(void)
+    constexpr int pop(void)
     {
-        // TODO: set error flag
         if (empty())
-            return 0xff;
+            return EOF;
 
         char c = _get_char(_backward(head));
         head = _backward(head);
         return c;
     }
 
-    constexpr char put(char c)
+    constexpr int put(char c)
     {
-        // TODO: set error flag
         if (full())
-            return 0xff;
+            return EOF;
 
         _put_char(c);
         head = _forward(head);

+ 3 - 9
include/types/string.hpp

@@ -91,23 +91,17 @@ public:
     }
     constexpr typename inner_vector_type::iterator_type back(void)
     {
-        // TODO: assert
-        if (this->empty())
-            return typename inner_vector_type::iterator_type((void*)0xffffffff);
+        assert(!this->empty());
         return --inner_vector_type::back();
     }
     constexpr typename inner_vector_type::const_iterator_type back(void) const
     {
-        // TODO: assert
-        if (this->empty())
-            return typename inner_vector_type::iterator_type((void*)0xffffffff);
+        assert(!this->empty());
         return --inner_vector_type::back();
     }
     constexpr typename inner_vector_type::const_iterator_type cback(void) const
     {
-        // TODO: assert
-        if (this->empty())
-            return typename inner_vector_type::iterator_type((void*)0xffffffff);
+        assert(!this->empty());
         return --inner_vector_type::cback();
     }
 };

+ 3 - 2
include/types/vector.hpp

@@ -1,5 +1,6 @@
 #pragma once
 
+#include <assert.h>
 #include <types/allocator.hpp>
 #include <types/cplusplus.hpp>
 #include <types/types.h>
@@ -230,13 +231,13 @@ public:
 
     constexpr value_type& at(index_type i) noexcept
     {
-        // TODO: boundary check
+        assert(i + 1 <= this->size());
         return _at(i);
     }
 
     constexpr const value_type& at(index_type i) const noexcept
     {
-        // TODO: boundary check
+        assert(i + 1 <= this->size());
         return _at(i);
     }
 

+ 13 - 2
src/kernel/interrupt.cpp

@@ -221,8 +221,19 @@ extern "C" void int14_handler(int14_data* d)
 
         // memory mapped
         if (d->error_code.present == 0) {
-            size_t offset = vptrdiff(d->l_addr, mm_area->start) & 0xfffff000;
-            vfs_read(mm_area->mapped_file, new_page_data, PAGE_SIZE, mm_area->file_offset + offset, PAGE_SIZE);
+            size_t offset = align_down<12>((uint32_t)d->l_addr);
+            offset -= (uint32_t)mm_area->start;
+
+            int n = vfs_read(
+                mm_area->mapped_file,
+                new_page_data,
+                PAGE_SIZE,
+                mm_area->file_offset + offset,
+                PAGE_SIZE);
+
+            // TODO: send SIGBUS if offset is greater than real size
+            if (n != PAGE_SIZE)
+                memset(new_page_data + n, 0x00, PAGE_SIZE - n);
         }
     }
 }

+ 11 - 7
src/kernel/mem.cpp

@@ -9,6 +9,7 @@
 #include <kernel/task.h>
 #include <kernel/vga.hpp>
 #include <kernel_main.hpp>
+#include <stdint.h>
 #include <stdio.h>
 #include <types/allocator.hpp>
 #include <types/bitmap.h>
@@ -451,14 +452,17 @@ static inline int _mmap(
         return GB_FAILED;
     }
 
-    len = (len + PAGE_SIZE - 1) & 0xfffff000;
-    size_t n_pgs = len >> 12;
+    // TODO: find another address
+    assert(((uint32_t)hint & 0xfff) == 0);
+    // TODO: return failed
+    assert((offset & 0xfff) == 0);
 
-    for (const auto& mm_area : *mms)
-        if (!mm_area.is_avail(hint, (char*)hint + len)) {
-            errno = EEXIST;
-            return GB_FAILED;
-        }
+    size_t n_pgs = align_up<12>(len) >> 12;
+
+    if (!mms->is_avail(hint, len)) {
+        errno = EEXIST;
+        return GB_FAILED;
+    }
 
     auto mm = mms->addarea(hint, write, priv);
     mm->mapped_file = file;

+ 30 - 11
src/types/elf.cpp

@@ -1,6 +1,8 @@
 #include <assert.h>
 #include <kernel/errno.h>
 #include <kernel/mem.h>
+#include <kernel/process.hpp>
+#include <kernel/vfs.hpp>
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
@@ -74,21 +76,38 @@ int types::elf::elf32_load(types::elf::elf32_load_data* d)
     current_process->mms.clear_user();
 
     for (int i = 0; i < hdr.phnum; ++i) {
-        if (phents->type != types::elf::elf32_program_header_entry::PT_LOAD)
+        if (phents[i].type != types::elf::elf32_program_header_entry::PT_LOAD)
             continue;
 
-        auto ret = mmap((void*)phents->vaddr, phents->memsz, ent_exec->ind, phents->offset, 1, d->system);
-        if (ret != GB_OK) {
-            k_free(phents);
-
-            // TODO: kill process
-            assert(false);
-
-            d->errcode = ret;
-            return GB_FAILED;
+        auto ret = mmap(
+            (char*)phents[i].vaddr,
+            phents[i].filesz,
+            ent_exec->ind,
+            phents[i].offset,
+            1,
+            d->system);
+
+        if (ret != GB_OK)
+            goto error;
+
+        if (phents[i].memsz > align_up<12>(phents[i].filesz)) {
+            ret = mmap(
+                (char*)phents[i].vaddr + align_up<12>(phents[i].filesz),
+                align_up<12>(phents[i].memsz) - align_up<12>(phents[i].filesz),
+                fs::vfs_open("/dev/null")->ind,
+                phents[i].offset + align_up<12>(phents[i].filesz),
+                1,
+                d->system);
+
+            if (ret != GB_OK)
+                goto error;
         }
 
-        ++phents;
+        continue;
+
+    error:
+        k_free(phents);
+        kill_current(-1);
     }
 
     // map stack area