diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml new file mode 100644 index 000000000..02b915b85 --- /dev/null +++ b/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/src/arch/x86/syscalls.cpp b/src/arch/x86/syscalls.cpp index fc2261a3f..87d68605e 100644 --- a/src/arch/x86/syscalls.cpp +++ b/src/arch/x86/syscalls.cpp @@ -215,14 +215,30 @@ char *syscall_sbrk(int brk) { if (!vma) return reinterpret_cast(-1); if (!vma->brk_start) { - vma->brk_start = (char *) vma->mmap_mem(nullptr, VMA::kBrkSize /* 16MB */, 0, PAGE_RW | PAGE_USER); + vma->brk_start = (char *) vma->mmap_mem((void *) 0x100000000ULL, VMA::kBrkSize, 0, PAGE_RW | PAGE_USER); if (!vma->brk_start) return reinterpret_cast(-1); // FIXME: vma->brk_end_real = *vma->brk_start + VMA::kBrkSize; vma->brk_end_fake = vma->brk_start; } - if (*vma->brk_end_fake + brk >= *vma->brk_start + VMA::kBrkSize) { - return ret; + if (*vma->brk_end_fake + brk > *vma->brk_end_real) { + size_t new_len = PAGE_ROUND_UP((*vma->brk_end_fake + brk - *vma->brk_end_real)); + void *new_end = vma->mmap_mem(*vma->brk_end_real, new_len, 0, PAGE_RW | PAGE_USER); + if (new_end != *vma->brk_end_real) { + writestr_no_yield("\nSBRK fail!\n"); + if (!vma->munmap(new_end, PAGE_ROUND_UP(*vma->brk_end_fake + brk - *vma->brk_end_real))) + writestr_no_yield("\nunmap fail after SBRK fail!\n"); + return reinterpret_cast(-1); + } + vma->brk_end_real = (char *) new_end + new_len; + } else if (*vma->brk_end_real - (*vma->brk_end_fake + brk) > 3 * PAGE_SIZE) { + uintptr_t new_end = PAGE_ROUND_UP((uintptr_t) (*vma->brk_end_fake + brk)); + uintptr_t length_diff = (uintptr_t) *vma->brk_end_real - new_end; + + if (vma->munmap((void *) new_end, length_diff) == -1) + writestr_no_yield("\nunmap fail in sbrk!\n"); + else + *vma->brk_end_real = (char *) new_end; } ret = *vma->brk_end_fake; diff --git a/src/arch/x86/task.cpp b/src/arch/x86/task.cpp index cfbca5e5a..7acc4abf0 100644 --- a/src/arch/x86/task.cpp +++ b/src/arch/x86/task.cpp @@ -194,9 +194,10 @@ void Task::user_setup() { _ownAddressSpace = UniquePtr(new AddressSpace()); _vma = UniquePtr(new VMA(_ownAddressSpace.get())); + static_assert(sizeof(task_pointer) <= PAGE_SIZE); task_pointer *taskptr = static_cast( _vma->mmap_mem(reinterpret_cast(TASK_POINTER), - sizeof(task_pointer), 0, PAGE_RW | PAGE_USER)); // FIXME: this is probably unsafe + PAGE_SIZE, 0, PAGE_RW | PAGE_USER)); // FIXME: this is probably unsafe assert((uintptr_t) taskptr == TASK_POINTER); task_pointer *taskptr_real = reinterpret_cast(HHDM_P2V(_ownAddressSpace->virt2real(taskptr))); @@ -224,9 +225,10 @@ void Task::user_reset() { _vma = UniquePtr(new VMA(_ownAddressSpace.get())); + static_assert(sizeof(task_pointer) <= PAGE_SIZE); task_pointer *taskptr = static_cast( _vma->mmap_mem(reinterpret_cast(TASK_POINTER), - sizeof(task_pointer), 0, PAGE_RW | PAGE_USER)); // FIXME: this is probably unsafe + PAGE_SIZE, 0, PAGE_RW | PAGE_USER)); // FIXME: this is probably unsafe assert((uintptr_t) taskptr == TASK_POINTER); task_pointer *taskptr_real = reinterpret_cast(HHDM_P2V(_ownAddressSpace->virt2real(taskptr))); diff --git a/src/kernel/VMA.cpp b/src/kernel/VMA.cpp index b2856252f..f91927b4e 100644 --- a/src/kernel/VMA.cpp +++ b/src/kernel/VMA.cpp @@ -81,13 +81,7 @@ void *VMA::mmap_phys(void *v_addr, void *real_addr, size_t length, int flags) { } void *VMA::mmap_mem(void *v_addr, size_t length, int prot, int flags) { - size_t origlen = length; - if ((length & (PAGE_SIZE - 1)) != 0) { - length += PAGE_SIZE - 1; - length &= ~(PAGE_SIZE - 1); - } assert((length & (PAGE_SIZE - 1)) == 0); - assert(length >= origlen); uint64_t page_len = length / PAGE_SIZE; @@ -107,6 +101,73 @@ void *VMA::mmap_mem(void *v_addr, size_t length, int prot, int flags) { return reinterpret_cast(found->begin); } int VMA::munmap(void *addr, size_t length) { + assert((length & (PAGE_SIZE - 1)) == 0); + assert((((uintptr_t) addr) & (PAGE_SIZE - 1)) == 0); + + uint64_t page_len = length / PAGE_SIZE; + + uintptr_t end = (uintptr_t) addr + length; + uintptr_t cur = (uintptr_t) addr; + + while (cur < end) { + LockGuard l(regions_lock); + auto found = regions.upper_bound(cur); + --found; + + if (found->second.type == EntryType::FREE) { + cur += found->second.length; + continue; + } + + ListEntry old = found->second; + regions.erase(found); + + if (old.begin < cur) + regions.emplace(std::make_pair((uintptr_t) old.begin, {old.begin, cur - old.begin, old.type, old.flags})); + + old.length = old.length - (cur - old.begin); + old.begin = cur; + + if (old.begin + old.length > end) + regions.emplace(std::make_pair((uintptr_t) end, {end, (old.begin + old.length) - end, old.type, old.flags})); + + old.length = std::min(old.length, length); + + size_t new_free_len = old.length; + + + uint64_t cur_page_len = new_free_len / PAGE_SIZE; + + for (int i = 0; i < cur_page_len; i++) { + free4k((void *) HHDM_P2V(space->virt2real(reinterpret_cast(old.begin + i * PAGE_SIZE)))); + { + LockGuard l(space_lock); + space->unmap(reinterpret_cast(old.begin + i * PAGE_SIZE)); + } + } + + // Merge free pages together + auto ub = regions.upper_bound(cur); + while (ub != regions.end() && ub->second.begin == (cur + new_free_len) && ub->second.type == EntryType::FREE) { + auto ubold = ub; + ++ub; + new_free_len += ubold->second.length; + regions.erase(ubold); + } + ub = regions.upper_bound(cur); + --ub; + while (ub != regions.end() && (ub->second.begin + ub->second.length) == cur && ub->second.type == EntryType::FREE) { + auto ubold = ub; + --ub; + cur = ubold->second.begin; + new_free_len += ubold->second.length; + regions.erase(ubold); + } + + regions.emplace(std::make_pair((uintptr_t) cur, {cur, new_free_len, EntryType::FREE, old.flags})); + + cur = cur + new_free_len; + } return 0; } VMA::~VMA() { diff --git a/src/kernel/VMA.hpp b/src/kernel/VMA.hpp index 041b4db9f..473cd1f27 100644 --- a/src/kernel/VMA.hpp +++ b/src/kernel/VMA.hpp @@ -16,11 +16,11 @@ class AddressSpace; class VMA { public: - VMA(AddressSpace *space); + VMA(AddressSpace *space); ~VMA(); - VMA(const VMA &) = delete; - VMA(VMA &&) = delete; + VMA(const VMA &) = delete; + VMA(VMA &&) = delete; VMA &operator=(const VMA &) = delete; VMA &operator=(VMA &&) = delete; @@ -32,7 +32,7 @@ public: void *mmap_mem(void *v_addr, size_t length, int prot, int flags); int munmap(void *addr, size_t length); - static constexpr size_t kBrkSize = 16ULL * 1024ULL * 1024ULL; + static constexpr size_t kBrkSize = 4096ULL * 20ULL; std::optional brk_start; std::optional brk_end_fake; std::optional brk_end_real; diff --git a/src/kernel/elf/ElfParser.cpp b/src/kernel/elf/ElfParser.cpp index 125d71704..2e6bff223 100644 --- a/src/kernel/elf/ElfParser.cpp +++ b/src/kernel/elf/ElfParser.cpp @@ -108,7 +108,7 @@ bool ElfParser::copy_to(Task *task) { } auto rounded_vaddr = hdr.p_vaddr & 0x000FFFFFFFFFF000ULL; - auto real_memsz = hdr.p_memsz + (hdr.p_vaddr - rounded_vaddr); + auto real_memsz = PAGE_ROUND_UP(hdr.p_memsz + (hdr.p_vaddr - rounded_vaddr)); uintptr_t real_ptr = reinterpret_cast(task->_vma->mmap_mem(reinterpret_cast(rounded_vaddr), real_memsz, 0, flags | PAGE_USER)); if (real_ptr != rounded_vaddr) return false; diff --git a/src/test/init.c b/src/test/init.c index dfb3e906b..000c39319 100644 --- a/src/test/init.c +++ b/src/test/init.c @@ -32,14 +32,6 @@ int main() { close(test123); printf("\n %s \n", buf); } - while (1) { - if (fork() == 0) - execve("hello2", 0, 0); - else - wait(NULL); - print_mem(); - sleep(500); - } while (1) { printf("\n> ");