greatbridf 1 год назад
Родитель
Сommit
8115a79f02
4 измененных файлов с 59 добавлено и 0 удалено
  1. 16 0
      include/kernel/mm.hpp
  2. 28 0
      src/kernel/mem.cpp
  3. 8 0
      src/kernel/syscall.cpp
  4. 7 0
      src/types/elf.cpp

+ 16 - 0
include/kernel/mm.hpp

@@ -195,6 +195,7 @@ public:
 private:
     list_type m_areas;
     page_t m_pd;
+    mm* m_brk {};
 
 public:
     // for system initialization only
@@ -213,6 +214,9 @@ public:
     ~mm_list();
     void switch_pd() const;
 
+    int register_brk(void* addr);
+    void* set_brk(void* addr);
+
     constexpr mm& addarea(void* start, bool w, bool system)
     {
         auto [ iter, inserted ] = m_areas.emplace(mm {
@@ -242,6 +246,7 @@ public:
             this->unmap(iter);
             iter = m_areas.erase(iter);
         }
+        m_brk = nullptr;
     }
 
     inline void unmap(iterator area)
@@ -267,6 +272,11 @@ public:
         types::pdelete<types::kernel_ident_allocator>(area->pgs);
     }
 
+    constexpr iterator iterfind(void* lp)
+    { return m_areas.find(lp); }
+    constexpr const_iterator iterfind(void* lp) const
+    { return m_areas.find(lp); }
+
     constexpr mm* find(void* lp)
     {
         auto iter = m_areas.find(lp);
@@ -292,6 +302,12 @@ public:
         }
         return true;
     }
+
+    constexpr bool is_avail(void* addr) const
+    {
+        auto iter = m_areas.find(addr);
+        return iter == m_areas.end();
+    }
 };
 
 } // namespace memory

+ 28 - 0
src/kernel/mem.cpp

@@ -215,6 +215,7 @@ mm_list::mm_list()
 mm_list::mm_list(const mm_list& other)
     : mm_list()
 {
+    m_brk = other.m_brk;
     for (auto& src : other.m_areas) {
         if (src.is_kernel_space() || src.attr.system)
             continue;
@@ -253,6 +254,33 @@ void mm_list::switch_pd() const
     asm_switch_pd(m_pd);
 }
 
+int mm_list::register_brk(void* addr)
+{
+    if (!is_avail(addr))
+        return GB_FAILED;
+    m_brk = &addarea(addr, true, false);
+    return GB_OK;
+}
+
+void* mm_list::set_brk(void* addr)
+{
+    assert(m_brk);
+    void* curbrk = m_brk->end();
+
+    if (addr <= curbrk || !is_avail(curbrk, vptrdiff(addr, curbrk)))
+        return curbrk;
+
+    kernel::paccess pa(m_pd);
+    pd_t pd = (pd_t)pa.ptr();
+
+    while (curbrk < addr) {
+        m_brk->append_page(pd, empty_page, PAGE_COW, false);
+        curbrk = (char*)curbrk + PAGE_SIZE;
+    }
+
+    return curbrk;
+}
+
 mm& mm_list::add_empty_area(void *start, std::size_t page_count,
     uint32_t page_attr, bool w, bool system)
 {

+ 8 - 0
src/kernel/syscall.cpp

@@ -569,6 +569,13 @@ int _syscall_getuid(interrupt_stack*)
     return 0; // all user is root for now
 }
 
+int _syscall_brk(interrupt_stack* data)
+{
+    SYSCALL_ARG1(void*, addr);
+
+    return (int)current_process->mms.set_brk(addr);
+}
+
 extern "C" void syscall_entry(interrupt_stack* data)
 {
     int syscall_no = SYSCALL_NO;
@@ -606,6 +613,7 @@ void init_syscall(void)
     syscall_handlers[0x14] = _syscall_getpid;
     syscall_handlers[0x29] = _syscall_dup;
     syscall_handlers[0x2a] = _syscall_pipe;
+    syscall_handlers[0x2d] = _syscall_brk;
     syscall_handlers[0x36] = _syscall_ioctl;
     syscall_handlers[0x39] = _syscall_setpgid;
     syscall_handlers[0x3f] = _syscall_dup2;

+ 7 - 0
src/types/elf.cpp

@@ -97,6 +97,8 @@ int types::elf::elf32_load(types::elf::elf32_load_data* d)
         null_ind = dent->ind;
     }
 
+    uint32_t data_segment_end = 0;
+
     for (const auto& phent : phents) {
         if (phent.type != types::elf::elf32_program_header_entry::PT_LOAD)
             continue;
@@ -129,8 +131,13 @@ int types::elf::elf32_load(types::elf::elf32_load_data* d)
             if (ret != GB_OK)
                 kill_current(-1);
         }
+
+        if (vaddr + vlen > data_segment_end)
+            data_segment_end = vaddr + vlen;
     }
 
+    current_process->mms.register_brk((char*)data_segment_end + 0x10000);
+
     for (const auto& shent : shents) {
         if (shent.sh_type == elf32_section_header_entry::SHT_NOBITS)
             memset((char*)shent.sh_addr, 0x00, shent.sh_size);