refactor: elf parsing utility and exec related
[lunaix-os.git] / lunaix-os / kernel / mm / mmap.c
index da1a0b6284f6d8103efe2ae333152ba824805e60..8eb7482b60af4b3bf7686a8e478ae0f54f1c7f52 100644 (file)
@@ -11,9 +11,8 @@
 #define BS_SIZE (KERNEL_MM_BASE - UMMAP_START)
 
 int
-mem_has_overlap(vm_regions_t* regions, ptr_t start, size_t len)
+mem_has_overlap(vm_regions_t* regions, ptr_t start, ptr_t end)
 {
-    ptr_t end = start + end - 1;
     struct mm_region *pos, *n;
     llist_for_each(pos, n, regions, head)
     {
@@ -33,6 +32,29 @@ mem_has_overlap(vm_regions_t* regions, ptr_t start, size_t len)
     return 0;
 }
 
+int
+mem_adjust_inplace(vm_regions_t* regions,
+                   struct mm_region* region,
+                   ptr_t newend)
+{
+    ssize_t len = newend - region->start;
+    if (len == 0) {
+        return 0;
+    }
+
+    if (len < 0) {
+        return EINVAL;
+    }
+
+    if (mem_has_overlap(regions, region->start, newend)) {
+        return ENOMEM;
+    }
+
+    region->end = newend;
+
+    return 0;
+}
+
 int
 mem_map(void** addr_out,
         struct mm_region** created,
@@ -48,7 +70,7 @@ mem_map(void** addr_out,
     vm_regions_t* vm_regions = &param->pvms->regions;
 
     if ((param->flags & MAP_FIXED_NOREPLACE)) {
-        if (mem_has_overlap(vm_regions, found_loc, param->mlen)) {
+        if (mem_has_overlap(vm_regions, found_loc, param->mlen + found_loc)) {
             return EEXIST;
         }
         goto found;
@@ -67,13 +89,13 @@ mem_map(void** addr_out,
     {
         if (last_end < found_loc) {
             size_t avail_space = pos->start - found_loc;
-            if ((int)avail_space > 0 && avail_space > param->mlen) {
+            if (pos->start > found_loc && avail_space > param->mlen) {
                 goto found;
             }
             found_loc = pos->end + PG_SIZE;
         }
 
-        last_end = pos->end + PG_SIZE;
+        last_end = pos->end;
     }
 
     return ENOMEM;
@@ -117,6 +139,15 @@ found:
     return 0;
 }
 
+int
+mem_remap(void** addr_out,
+          struct mm_region** remapped,
+          void* addr,
+          struct v_file* file,
+          struct mmap_param* param)
+{
+}
+
 void
 mem_sync_pages(ptr_t mnt,
                struct mm_region* region,
@@ -213,7 +244,7 @@ mem_unmap(ptr_t mnt, vm_regions_t* regions, void* addr, size_t length)
         }
     }
 
-    while (&pos->head != regions && cur_addr > pos->start) {
+    while (&pos->head != regions && cur_addr >= pos->start) {
         u32_t l = pos->end - cur_addr;
         pos->end = cur_addr;
 
@@ -266,24 +297,25 @@ __DEFINE_LXSYSCALL3(void*, sys_mmap, void*, addr, size_t, length, va_list, lst)
     if (!addr) {
         addr = UMMAP_START;
     } else if (addr < UMMAP_START || addr + length >= UMMAP_END) {
-        errno = ENOMEM;
-        goto done;
-    }
-
-    struct v_fd* vfd;
-    if ((errno = vfs_getfd(fd, &vfd))) {
-        goto done;
+        if (!(options & (MAP_FIXED | MAP_FIXED_NOREPLACE))) {
+            errno = ENOMEM;
+            goto done;
+        }
     }
 
-    struct v_file* file = vfd->file;
+    struct v_file* file = NULL;
 
     if (!(options & MAP_ANON)) {
+        struct v_fd* vfd;
+        if ((errno = vfs_getfd(fd, &vfd))) {
+            goto done;
+        }
+
+        file = vfd->file;
         if (!file->ops->read_page) {
             errno = ENODEV;
             goto done;
         }
-    } else {
-        file = NULL;
     }
 
     struct mmap_param param = { .flags = options,