mirror of
https://github.com/usatiuk/ficus.git
synced 2025-10-29 00:27:52 +01:00
VMA unmap
This commit is contained in:
15
.idea/git_toolbox_prj.xml
generated
Normal file
15
.idea/git_toolbox_prj.xml
generated
Normal 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>
|
||||||
@@ -215,14 +215,30 @@ char *syscall_sbrk(int brk) {
|
|||||||
if (!vma) return reinterpret_cast<char *>(-1);
|
if (!vma) return reinterpret_cast<char *>(-1);
|
||||||
|
|
||||||
if (!vma->brk_start) {
|
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:
|
if (!vma->brk_start) return reinterpret_cast<char *>(-1); // FIXME:
|
||||||
vma->brk_end_real = *vma->brk_start + VMA::kBrkSize;
|
vma->brk_end_real = *vma->brk_start + VMA::kBrkSize;
|
||||||
vma->brk_end_fake = vma->brk_start;
|
vma->brk_end_fake = vma->brk_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*vma->brk_end_fake + brk >= *vma->brk_start + VMA::kBrkSize) {
|
if (*vma->brk_end_fake + brk > *vma->brk_end_real) {
|
||||||
return ret;
|
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;
|
ret = *vma->brk_end_fake;
|
||||||
|
|||||||
@@ -194,9 +194,10 @@ void Task::user_setup() {
|
|||||||
_ownAddressSpace = UniquePtr(new AddressSpace());
|
_ownAddressSpace = UniquePtr(new AddressSpace());
|
||||||
_vma = UniquePtr<VMA>(new VMA(_ownAddressSpace.get()));
|
_vma = UniquePtr<VMA>(new VMA(_ownAddressSpace.get()));
|
||||||
|
|
||||||
|
static_assert(sizeof(task_pointer) <= PAGE_SIZE);
|
||||||
task_pointer *taskptr = static_cast<task_pointer *>(
|
task_pointer *taskptr = static_cast<task_pointer *>(
|
||||||
_vma->mmap_mem(reinterpret_cast<void *>(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);
|
assert((uintptr_t) taskptr == TASK_POINTER);
|
||||||
|
|
||||||
task_pointer *taskptr_real = reinterpret_cast<task_pointer *>(HHDM_P2V(_ownAddressSpace->virt2real(taskptr)));
|
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()));
|
_vma = UniquePtr<VMA>(new VMA(_ownAddressSpace.get()));
|
||||||
|
|
||||||
|
static_assert(sizeof(task_pointer) <= PAGE_SIZE);
|
||||||
task_pointer *taskptr = static_cast<task_pointer *>(
|
task_pointer *taskptr = static_cast<task_pointer *>(
|
||||||
_vma->mmap_mem(reinterpret_cast<void *>(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);
|
assert((uintptr_t) taskptr == TASK_POINTER);
|
||||||
|
|
||||||
task_pointer *taskptr_real = reinterpret_cast<task_pointer *>(HHDM_P2V(_ownAddressSpace->virt2real(taskptr)));
|
task_pointer *taskptr_real = reinterpret_cast<task_pointer *>(HHDM_P2V(_ownAddressSpace->virt2real(taskptr)));
|
||||||
|
|||||||
@@ -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) {
|
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 & (PAGE_SIZE - 1)) == 0);
|
||||||
assert(length >= origlen);
|
|
||||||
|
|
||||||
uint64_t page_len = length / PAGE_SIZE;
|
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);
|
return reinterpret_cast<void *>(found->begin);
|
||||||
}
|
}
|
||||||
int VMA::munmap(void *addr, size_t length) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
VMA::~VMA() {
|
VMA::~VMA() {
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ class AddressSpace;
|
|||||||
|
|
||||||
class VMA {
|
class VMA {
|
||||||
public:
|
public:
|
||||||
VMA(AddressSpace *space);
|
VMA(AddressSpace *space);
|
||||||
~VMA();
|
~VMA();
|
||||||
|
|
||||||
VMA(const VMA &) = delete;
|
VMA(const VMA &) = delete;
|
||||||
VMA(VMA &&) = delete;
|
VMA(VMA &&) = delete;
|
||||||
VMA &operator=(const VMA &) = delete;
|
VMA &operator=(const VMA &) = delete;
|
||||||
VMA &operator=(VMA &&) = delete;
|
VMA &operator=(VMA &&) = delete;
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ public:
|
|||||||
void *mmap_mem(void *v_addr, size_t length, int prot, int flags);
|
void *mmap_mem(void *v_addr, size_t length, int prot, int flags);
|
||||||
int munmap(void *addr, size_t length);
|
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_start;
|
||||||
std::optional<char *> brk_end_fake;
|
std::optional<char *> brk_end_fake;
|
||||||
std::optional<char *> brk_end_real;
|
std::optional<char *> brk_end_real;
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ bool ElfParser::copy_to(Task *task) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto rounded_vaddr = hdr.p_vaddr & 0x000FFFFFFFFFF000ULL;
|
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));
|
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;
|
if (real_ptr != rounded_vaddr) return false;
|
||||||
|
|||||||
@@ -32,14 +32,6 @@ int main() {
|
|||||||
close(test123);
|
close(test123);
|
||||||
printf("\n %s \n", buf);
|
printf("\n %s \n", buf);
|
||||||
}
|
}
|
||||||
while (1) {
|
|
||||||
if (fork() == 0)
|
|
||||||
execve("hello2", 0, 0);
|
|
||||||
else
|
|
||||||
wait(NULL);
|
|
||||||
print_mem();
|
|
||||||
sleep(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
printf("\n> ");
|
printf("\n> ");
|
||||||
|
|||||||
Reference in New Issue
Block a user