VMA unmap

This commit is contained in:
2024-04-14 18:18:25 +02:00
parent 63af59f5ac
commit 19a107e3a0
7 changed files with 110 additions and 24 deletions

15
.idea/git_toolbox_prj.xml generated Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageIssueKeyValidationOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
<option name="commitMessageValidationEnabledOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
</component>
</project>

View File

@@ -215,14 +215,30 @@ char *syscall_sbrk(int brk) {
if (!vma) return reinterpret_cast<char *>(-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<char *>(-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<char *>(-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;

View File

@@ -194,9 +194,10 @@ void Task::user_setup() {
_ownAddressSpace = UniquePtr(new AddressSpace());
_vma = UniquePtr<VMA>(new VMA(_ownAddressSpace.get()));
static_assert(sizeof(task_pointer) <= PAGE_SIZE);
task_pointer *taskptr = static_cast<task_pointer *>(
_vma->mmap_mem(reinterpret_cast<void *>(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<task_pointer *>(HHDM_P2V(_ownAddressSpace->virt2real(taskptr)));
@@ -224,9 +225,10 @@ void Task::user_reset() {
_vma = UniquePtr<VMA>(new VMA(_ownAddressSpace.get()));
static_assert(sizeof(task_pointer) <= PAGE_SIZE);
task_pointer *taskptr = static_cast<task_pointer *>(
_vma->mmap_mem(reinterpret_cast<void *>(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<task_pointer *>(HHDM_P2V(_ownAddressSpace->virt2real(taskptr)));

View File

@@ -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<void *>(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, ListEntry>((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, ListEntry>((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<void *>(old.begin + i * PAGE_SIZE))));
{
LockGuard l(space_lock);
space->unmap(reinterpret_cast<void *>(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, ListEntry>((uintptr_t) cur, {cur, new_free_len, EntryType::FREE, old.flags}));
cur = cur + new_free_len;
}
return 0;
}
VMA::~VMA() {

View File

@@ -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<char *> brk_start;
std::optional<char *> brk_end_fake;
std::optional<char *> brk_end_real;

View File

@@ -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<uintptr_t>(task->_vma->mmap_mem(reinterpret_cast<void *>(rounded_vaddr), real_memsz, 0, flags | PAGE_USER));
if (real_ptr != rounded_vaddr) return false;

View File

@@ -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> ");