regression: mmap for fd
authorMinep <zelong56@gmail.com>
Wed, 28 Dec 2022 23:19:19 +0000 (23:19 +0000)
committerMinep <zelong56@gmail.com>
Wed, 28 Dec 2022 23:19:19 +0000 (23:19 +0000)
fix: replace %ebp register to %esi for passing 5-th arg when switching to syscall dispatcher.
feat: support for anonymous mapping
refactor: mm_region interfaces
refactor: page fault handler clean up.
refactor: resolve cyclic dependencies between mm.h and fs.h
refactor: rename readdir to sys_readdir to distinguish readdir(3)
wip refactor: separating syscall definitions to userspace.

29 files changed:
lunaix-os/arch/x86/boot.S
lunaix-os/includes/lunaix/fctrl.h
lunaix-os/includes/lunaix/fs.h
lunaix-os/includes/lunaix/mm/mm.h
lunaix-os/includes/lunaix/mm/mmap.h
lunaix-os/includes/lunaix/mm/page.h
lunaix-os/includes/lunaix/mm/region.h
lunaix-os/includes/lunaix/process.h
lunaix-os/includes/lunaix/syscall.h
lunaix-os/includes/lunaix/syscall_utils.h [new file with mode: 0644]
lunaix-os/includes/lunaix/types.h
lunaix-os/includes/usr/sys/mann.h [new file with mode: 0644]
lunaix-os/includes/usr/sys/mann_flags.h [new file with mode: 0644]
lunaix-os/includes/usr/sys/types.h [new file with mode: 0644]
lunaix-os/kernel/asm/x86/pfault.c
lunaix-os/kernel/asm/x86/syscall.S
lunaix-os/kernel/demos/dir_read.c
lunaix-os/kernel/demos/simple_sh.c
lunaix-os/kernel/device/device.c
lunaix-os/kernel/fs/mount.c
lunaix-os/kernel/fs/path_walk.c
lunaix-os/kernel/fs/vfs.c
lunaix-os/kernel/fs/xattr.c
lunaix-os/kernel/mm/mmap.c
lunaix-os/kernel/mm/region.c
lunaix-os/kernel/process/process.c
lunaix-os/kernel/process/sched.c
lunaix-os/kernel/process/task_attr.c
lunaix-os/usr/api/mann.c [new file with mode: 0644]

index 9e44437c7803d24b40323c6d69f3a67b455b5f37..d1d14ba7e8af8ded3708aab9aa81fb330d65f62a 100644 (file)
@@ -78,7 +78,7 @@
         movl %eax, %cr3
 
         movl %cr0, %eax
-        orl $0x80010000, %eax   /* 开启分页与地址转换 (CR0.PG=1, CR0.WP=1) */
+        orl $0x80000000, %eax   /* 开启分页与地址转换 (CR0.PG=1, CR0.WP=0) */
         andl $0xfffffffb, %eax
         orl $0x2, %eax          /* 启用x87 FPU (CR0.MP=1, CR0.EM=0) */
         movl %eax, %cr0
index 5ec0eef3d7891a6ad59c89db7ca59ec444842e93..36efb4b50ba778df6699c0315c4614f3e9ca4453 100644 (file)
@@ -10,7 +10,7 @@ __LXSYSCALL2(int, open, const char*, path, int, options)
 __LXSYSCALL1(int, mkdir, const char*, path)
 __LXSYSCALL2(int, unlinkat, int, fd, const char*, pathname)
 
-__LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent)
+__LXSYSCALL2(int, sys_readdir, int, fd, struct dirent*, dent)
 
 __LXSYSCALL4(int,
              readlinkat,
index 3ec85f5c2b711fce57f8b273af22694d0c1da571..59faabc57c2bf30e0d64fefba0cda056f7a7abd8 100644 (file)
@@ -9,7 +9,6 @@
 #include <lunaix/ds/llist.h>
 #include <lunaix/ds/lru.h>
 #include <lunaix/ds/mutex.h>
-#include <lunaix/process.h>
 #include <lunaix/status.h>
 #include <stdatomic.h>
 
@@ -36,9 +35,6 @@
 
 #define FSTYPE_ROFS 0x1
 
-#define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno)
-#define DO_STATUS_OR_RETURN(errno) ({ errno < 0 ? DO_STATUS(errno) : errno; })
-
 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
 
 #define VFS_VALID_CHAR(chr)                                                    \
index 07d3d791df3f12fa05c6bbc52a6a7c11d5bc1243..5890f6181e677c95a81d768f7b2acbff1ae2eb29 100644 (file)
@@ -6,6 +6,8 @@
 #include <lunaix/fs.h>
 #include <lunaix/types.h>
 
+#include <usr/sys/mann_flags.h>
+
 typedef struct
 {
     void* start;
@@ -18,28 +20,29 @@ typedef struct
  * @brief 私有区域,该区域中的页无法进行任何形式的共享。
  *
  */
-#define REGION_PRIVATE 0x0
+#define REGION_PRIVATE MAP_PRIVATE
 
 /**
  * @brief
  * 读共享区域,该区域中的页可以被两个进程之间读共享,但任何写操作须应用Copy-On-Write
  *
  */
-#define REGION_RSHARED 0x1
+#define REGION_RSHARED MAP_RSHARED
 
 /**
  * @brief
  * 写共享区域,该区域中的页可以被两个进程之间读共享,任何的写操作无需执行Copy-On-Write
  *
  */
-#define REGION_WSHARED 0x2
+#define REGION_WSHARED MAP_WSHARED
 
 #define REGION_PERM_MASK 0x1c
 #define REGION_MODE_MASK 0x3
 
-#define REGION_READ (1 << 2)
-#define REGION_WRITE (1 << 3)
-#define REGION_EXEC (1 << 4)
+#define REGION_READ PROT_READ
+#define REGION_WRITE PROT_WRITE
+#define REGION_EXEC PROT_EXEC
+#define REGION_ANON MAP_ANON
 #define REGION_RW REGION_READ | REGION_WRITE
 
 #define REGION_TYPE_CODE (1 << 16);
@@ -49,7 +52,7 @@ typedef struct
 
 struct mm_region
 {
-    struct llist_header head;
+    struct llist_header head; // must be first field!
     struct v_file* mfile;
     u32_t offset;
     ptr_t start;
index 78c12d6f5839c631d6b564a60f7cb77c78411adf..333504a203c2c40bbaa5063e5fde706632950471 100644 (file)
@@ -2,18 +2,20 @@
 #define __LUNAIX_MMAP_H
 
 #include <lunaix/fs.h>
+#include <lunaix/mm/region.h>
 #include <lunaix/types.h>
 
 void*
 mem_map(ptr_t pd_ref,
-        struct llist_header* regions,
+        vm_regions_t* regions,
         void* addr,
         struct v_file* file,
-        u32_t offset,
+        off_t offset,
         size_t length,
-        u32_t attrs);
+        u32_t attrs,
+        u32_t options);
 
 void*
-mem_unmap(ptr_t mnt, struct llist_header* regions, void* addr, size_t length);
+mem_unmap(ptr_t mnt, vm_regions_t* regions, void* addr, size_t length);
 
 #endif /* __LUNAIX_MMAP_H */
index 37496a384a63583b465325041001e6f56f612012..8d479c2f47f3305b7d1669d938a63c47672496ee 100644 (file)
@@ -23,6 +23,7 @@
 
 #define PG_DIRTY(pte) ((pte & (1 << 6)) >> 6)
 #define PG_ACCESSED(pte) ((pte & (1 << 5)) >> 5)
+#define PG_PRESENTED(pte) ((pte)&PG_PRESENT)
 
 #define IS_CACHED(entry) ((entry & 0x1))
 
index c1c8074e756c096b4d50ffcfc8db0f07f62a8e0c..be4a30065498a78c933b9ba288a55fb067ec95af 100644 (file)
@@ -3,16 +3,21 @@
 
 #include <lunaix/mm/mm.h>
 
+typedef struct llist_header vm_regions_t;
+
 struct mm_region*
-region_add(struct llist_header* lead, ptr_t start, ptr_t end, u32_t attr);
+region_create(ptr_t start, ptr_t end, u32_t attr);
+
+void
+region_add(vm_regions_t* lead, struct mm_region* vmregion);
 
 void
-region_release_all(struct llist_header* lead);
+region_release_all(vm_regions_t* lead);
 
 struct mm_region*
-region_get(struct llist_header* lead, unsigned long vaddr);
+region_get(vm_regions_t* lead, unsigned long vaddr);
 
 void
-region_copy(struct llist_header* src, struct llist_header* dest);
+region_copy(vm_regions_t* src, vm_regions_t* dest);
 
 #endif /* __LUNAIX_REGION_H */
index 1eacf127a28e31ea567a42f12b8b680e69533f8a..ab5dde9d64601be5b083c147c28f1339e182d203 100644 (file)
@@ -6,6 +6,7 @@
 #include <lunaix/ds/waitq.h>
 #include <lunaix/fs.h>
 #include <lunaix/mm/mm.h>
+#include <lunaix/mm/region.h>
 #include <lunaix/signal.h>
 #include <lunaix/timer.h>
 #include <lunaix/types.h>
@@ -28,7 +29,7 @@
 struct proc_mm
 {
     heap_context_t u_heap;
-    struct llist_header regions;
+    vm_regions_t regions;
 };
 
 struct proc_sigstate
index 04ae40bc88964e7d1a1d242da69ef561a8dd4514..8da4dc5c91b65458f980259839f156aa94c26e09 100644 (file)
@@ -27,7 +27,7 @@
 
 #define __SYSCALL_read 21
 #define __SYSCALL_write 22
-#define __SYSCALL_readdir 23
+#define __SYSCALL_sys_readdir 23
 #define __SYSCALL_mkdir 24
 #define __SYSCALL_lseek 25
 #define __SYSCALL_geterrno 26
@@ -60,7 +60,7 @@
 
 #define __SYSCALL_syslog 51
 
-#define __SYSCALL_mmap 52
+#define __SYSCALL_sys_mmap 52
 #define __SYSCALL_munmap 53
 
 #define __SYSCALL_MAX 0x100
@@ -148,8 +148,7 @@ syscall_install();
 #define __LXSYSCALL5(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5)    \
     static rettype name(__PARAM_MAP5(t1, p1, t2, p2, t3, p3, t4, p4, t5, p5))  \
     {                                                                          \
-        asm("movl %0, %%ebp\n" ::"r"(p5), "b"(p1), "c"(p2), "d"(p3), "D"(p4)   \
-            : "%ebp");                                                         \
+        asm("" ::"r"(p5), "b"(p1), "c"(p2), "d"(p3), "D"(p4), "S"(p5));        \
         ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
 
@@ -162,6 +161,6 @@ syscall_install();
         asm("\n" ::"b"(p1), "c"(p2), "d"(_last));                              \
         ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
-#endif
 
+#endif
 #endif /* __LUNAIX_SYSCALL_H */
diff --git a/lunaix-os/includes/lunaix/syscall_utils.h b/lunaix-os/includes/lunaix/syscall_utils.h
new file mode 100644 (file)
index 0000000..fcc7dc3
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __LUNAIX_SYSCALL_UTILS_H
+#define __LUNAIX_SYSCALL_UTILS_H
+
+#include <lunaix/process.h>
+#include <lunaix/syscall.h>
+
+#define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno)
+#define DO_STATUS_OR_RETURN(errno) ({ errno < 0 ? DO_STATUS(errno) : errno; })
+
+#endif /* __LUNAIX_SYSCALL_UTILS_H */
index f99620f9aff93b52e8def4a70e470464fa253f74..0d1ad197fa05c8bb75bf4916ab7192c1e97ea431 100644 (file)
@@ -2,8 +2,8 @@
 #define __LUNAIX_TYPES_H
 
 #include <stdarg.h>
-#include <stddef.h>
 #include <stdint.h>
+#include <usr/sys/types.h>
 
 #define PEXITTERM 0x100
 #define PEXITSTOP 0x200
@@ -31,9 +31,7 @@ typedef unsigned short u16_t;
 typedef unsigned int u32_t;
 typedef unsigned long long u64_t;
 typedef unsigned long ptr_t;
-typedef signed long ssize_t;
 
-typedef int32_t pid_t;
 typedef int64_t lba_t;
 
 #endif /* __LUNAIX_TYPES_H */
diff --git a/lunaix-os/includes/usr/sys/mann.h b/lunaix-os/includes/usr/sys/mann.h
new file mode 100644 (file)
index 0000000..140ef35
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __LUNAIX_SYS_MANN_H
+#define __LUNAIX_SYS_MANN_H
+
+#include <usr/sys/mann_flags.h>
+#include <usr/sys/types.h>
+
+void*
+mmap(void* addr, size_t length, int proct, int flags, int fd, off_t offset);
+
+void
+munmap(void* addr, size_t length);
+
+#endif /* __LUNAIX_MANN_H */
diff --git a/lunaix-os/includes/usr/sys/mann_flags.h b/lunaix-os/includes/usr/sys/mann_flags.h
new file mode 100644 (file)
index 0000000..3168d63
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __LUNAIX_SYS_MANN_FLAGS_H
+#define __LUNAIX_SYS_MANN_FLAGS_H
+
+// POSIX compliant.
+
+// identity mapped to region attributes
+#define PROT_READ (1 << 2)
+#define PROT_WRITE (1 << 3)
+#define PROT_EXEC (1 << 4)
+
+// identity mapped to region attributes
+#define MAP_WSHARED 0x2
+#define MAP_RSHARED 0x1
+#define MAP_SHARED (MAP_WSHARED | MAP_RSHARED)
+#define MAP_PRIVATE 0x0
+#define MAP_ANON (1 << 5)
+#define MAP_STACK 0 // no effect in Lunaix
+// other MAP_* goes should beyond 0x20
+
+#define MS_ASYNC 0x1
+#define MS_SYNC 0x2
+#define MS_INVALIDATE 0x4
+
+#endif /* __LUNAIX_MANN_FLAGS_H */
diff --git a/lunaix-os/includes/usr/sys/types.h b/lunaix-os/includes/usr/sys/types.h
new file mode 100644 (file)
index 0000000..712d687
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __LUNAIX_SYS_TYPES_H
+#define __LUNAIX_SYS_TYPES_H
+
+typedef signed long ssize_t;
+
+typedef int pid_t;
+
+typedef unsigned long size_t;
+
+typedef unsigned long off_t;
+
+#endif /* __LUNAIX_TYPES_H */
index 64986190bddf58c85cc5c2cc3c792267d6730151..bbaf59f407655225f86794fd6c0025e3af7c7374 100644 (file)
@@ -9,6 +9,8 @@
 #include <lunaix/status.h>
 #include <lunaix/syslog.h>
 
+#include <klibc/string.h>
+
 static void
 kprintf(const char* fmt, ...)
 {
@@ -52,7 +54,7 @@ intr_routine_page_fault(const isr_param* param)
     }
 
     volatile x86_pte_t* pte = &PTE_MOUNTED(PD_REFERENCED, ptr >> 12);
-    if ((*pte & PG_PRESENT)) {
+    if (PG_PRESENTED(*pte)) {
         if ((hit_region->attr & COW_MASK) == COW_MASK) {
             // normal page fault, do COW
             cpu_invplg(pte);
@@ -66,28 +68,25 @@ intr_routine_page_fault(const isr_param* param)
         goto segv_term;
     }
 
-    // if (!(*pte)) {
-    //     // Invalid location
-    //     goto segv_term;
-    // }
-
-    uintptr_t loc = *pte & ~0xfff;
-
-    // a writable page, not present, not cached, pte attr is not null
+    // an anonymous page and not present
     //   -> a new page need to be alloc
-    if ((hit_region->attr & REGION_WRITE) && (*pte & 0xfff) && !loc) {
-        cpu_invplg(pte);
-        uintptr_t pa = pmm_alloc_page(__current->pid, 0);
-        if (!pa) {
-            goto oom;
-        }
+    if ((hit_region->attr & REGION_ANON)) {
+        if (!PG_PRESENTED(*pte)) {
+            cpu_invplg(pte);
+            uintptr_t pa = pmm_alloc_page(__current->pid, 0);
+            if (!pa) {
+                goto oom;
+            }
 
-        *pte = *pte | pa | PG_PRESENT;
-        goto resolved;
+            *pte = *pte | pa | PG_PRESENT;
+            goto resolved;
+        }
+        // permission denied on anon page
+        goto segv_term;
     }
 
-    // if mfile is set, then it is a mem map
-    if (hit_region->mfile) {
+    // if mfile is set (Non-anonymous), then it is a mem map
+    if (hit_region->mfile && !PG_PRESENTED(*pte)) {
         struct v_file* file = hit_region->mfile;
         u32_t offset =
           (ptr - hit_region->start) & (PG_SIZE - 1) + hit_region->offset;
@@ -98,17 +97,21 @@ intr_routine_page_fault(const isr_param* param)
         }
 
         cpu_invplg(pte);
-        *pte = *pte | pa | PG_PRESENT;
-        int errno = file->ops->read_page(
-          file->inode, ptr & (PG_SIZE - 1), PG_SIZE, offset);
+        *pte = (*pte & 0xFFF) | pa | PG_PRESENT;
+
+        ptr = ptr & ~(PG_SIZE - 1);
+        memset(ptr, 0, PG_SIZE);
+
+        int errno = file->ops->read_page(file->inode, ptr, PG_SIZE, offset);
         if (errno < 0) {
             kprintf(KERROR "fail to read page (%d)\n", errno);
             goto segv_term;
         }
+
         goto resolved;
     }
 
-    // page not present, bring it from disk or somewhere else
+    // page not present, might be a chance to introduce swap file?
     __print_panic_msg("WIP page fault route", param);
     while (1)
         ;
index bd51976d64fc2a5f9801dba7e7fde6cb8a3ef44d..eb167836cdf3917455e94720a82c7c802b38a067 100644 (file)
@@ -30,7 +30,7 @@
         .long __lxsys_close         /* 20 */
         .long __lxsys_read
         .long __lxsys_write
-        .long __lxsys_readdir
+        .long __lxsys_sys_readdir
         .long __lxsys_mkdir
         .long __lxsys_lseek         /* 25 */
         .long __lxsys_geterrno
@@ -59,7 +59,7 @@
         .long __lxsys_getpgid
         .long __lxsys_setpgid       /* 50 */
         .long __lxsys_syslog
-        .long __lxsys_mmap
+        .long __lxsys_sys_mmap
         .long __lxsys_munmap
         2:
         .rept __SYSCALL_MAX - (2b - 1b)/4
@@ -86,8 +86,7 @@
         popl  %ebp
         ret
     1:
-        pushl 24(%ebp)      /* esi - #6 arg */
-        pushl 20(%ebp)      /* ebp - #5 arg */
+        pushl 24(%ebp)      /* esi - #5 arg */
         pushl 16(%ebp)      /* edi - #4 arg */
         pushl 12(%ebp)      /* edx - #3 arg */
         pushl 8(%ebp)       /* ecx - #2 arg */
@@ -97,7 +96,7 @@
 
         movl %eax, (%ebp)    /* save the return value */
 
-        addl $24, %esp      /* remove the parameters from stack */
+        addl $20, %esp      /* remove the parameters from stack */
 
         popl %ebp
         
index e1ef7a21e19b28c90c025f638ad49867973f6f77..70070a1eafe3753413a5691e119d3f0f381b4689 100644 (file)
@@ -23,7 +23,7 @@ _readdir_main()
 
     struct dirent ent = { .d_offset = 0 };
 
-    while (readdir(fd, &ent) == 1) {
+    while (sys_readdir(fd, &ent) == 1) {
         printf("%s\n", ent.d_name);
     }
 
index acebe211de046867f99bc1cc2503d9cdbd93f363..8bb357bef15f741b284da29f6f0fb7e6008c97f3 100644 (file)
@@ -6,6 +6,8 @@
 #include <lunaix/signal.h>
 #include <lunaix/status.h>
 
+#include <usr/sys/mann.h>
+
 #include <klibc/string.h>
 #include <ulibc/stdio.h>
 
@@ -101,7 +103,7 @@ do_ls(const char* path)
     } else {
         struct dirent ent = { .d_offset = 0 };
         int status;
-        while ((status = readdir(fd, &ent)) == 1) {
+        while ((status = sys_readdir(fd, &ent)) == 1) {
             if (ent.d_type == DT_DIR) {
                 printf(" \033[3m%s\033[39;49m\n", ent.d_name);
             } else {
@@ -116,6 +118,25 @@ do_ls(const char* path)
     }
 }
 
+void
+do_mcat(const char* file)
+{
+    int fd = open(file, 0);
+    if (fd < 0) {
+        sh_printerr();
+    } else {
+        ptr_t p = mmap(NULL, 2048, 0, 0, fd, 0);
+        if ((int)p < 0) {
+            sh_printerr();
+        } else {
+            printf("%s\n", p);
+        }
+        munmap(p, 1);
+        close(fd);
+        printf("\n");
+    }
+}
+
 void
 sh_loop()
 {
@@ -161,6 +182,11 @@ sh_loop()
                 do_cat(argpart);
                 _exit(0);
             }
+        } else if (streq(cmd, "mcat")) {
+            if (!(p = fork())) {
+                do_mcat(argpart);
+                _exit(0);
+            }
         } else {
             printf("unknow command\n");
             goto cont;
index b784fdbf4c3649bfcf49d99781dfa139da9a2846..3647f10a87f778395cb4efba6f4080b622cd0f63 100644 (file)
@@ -6,6 +6,7 @@
 #include <lunaix/mm/valloc.h>
 #include <lunaix/spike.h>
 #include <lunaix/syscall.h>
+#include <lunaix/syscall_utils.h>
 
 static DEFINE_LLIST(root_list);
 
index 7db951389e3866499f772e201e9a49eff8c118f5..12e1d4b94c273acc87df26203f8ea96c2b611711 100644 (file)
@@ -3,6 +3,7 @@
 #include <lunaix/mm/valloc.h>
 #include <lunaix/process.h>
 #include <lunaix/spike.h>
+#include <lunaix/syscall_utils.h>
 #include <lunaix/syslog.h>
 #include <lunaix/types.h>
 
index a0331e70139d644b1a4657d2c9d64aaa404bfe04..cd0ac01565e4616ca68901a8ccaa7ed2938b244b 100644 (file)
@@ -1,5 +1,6 @@
 #include <lunaix/fs.h>
 #include <lunaix/mm/valloc.h>
+#include <lunaix/process.h>
 #include <lunaix/spike.h>
 
 #include <klibc/string.h>
index 9680f2e9056a274b734d048853c4001cea05e254..cbe3c39ab507a8021d453b01ab38f07803858bdb 100644 (file)
@@ -53,6 +53,7 @@
 #include <lunaix/process.h>
 #include <lunaix/spike.h>
 #include <lunaix/syscall.h>
+#include <lunaix/syscall_utils.h>
 
 #include <lunaix/fs/twifs.h>
 
@@ -630,7 +631,7 @@ __vfs_readdir_callback(struct dir_context* dctx,
     dent->d_type = dtype;
 }
 
-__DEFINE_LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent)
+__DEFINE_LXSYSCALL2(int, sys_readdir, int, fd, struct dirent*, dent)
 {
     struct v_fd* fd_s;
     int errno;
index 94f85b76dce7489708124e87a8a34f7988e4451d..6fdb300727f574972c5c3b99d104956681111efd 100644 (file)
@@ -1,7 +1,11 @@
 #include <klibc/string.h>
 #include <lunaix/fs.h>
 #include <lunaix/mm/valloc.h>
+#include <lunaix/process.h>
 #include <lunaix/syscall.h>
+#include <lunaix/syscall_utils.h>
+
+#define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno)
 
 struct v_xattr_entry*
 xattr_new(struct hstr* name)
index 8eb6b2007ff989f058c74833c38e4d27ba3ec762..7b8ce8fb81f79f810ab6aacdadafa297ef4603c2 100644 (file)
@@ -1,6 +1,5 @@
 #include <lunaix/mm/mmap.h>
 #include <lunaix/mm/pmm.h>
-#include <lunaix/mm/region.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/mm/vmm.h>
 #include <lunaix/spike.h>
@@ -9,12 +8,13 @@
 
 void*
 mem_map(ptr_t mnt,
-        struct llist_header* regions,
+        vm_regions_t* regions,
         void* addr,
         struct v_file* file,
-        u32_t offset,
+        off_t offset,
         size_t length,
-        u32_t proct)
+        u32_t proct,
+        u32_t options)
 {
     if (!length || (length & (PG_SIZE - 1)) || (offset & (PG_SIZE - 1))) {
         __current->k_status = EINVAL;
@@ -44,10 +44,13 @@ found:
     addr = last_end;
     ptr_t end = addr + length;
 
-    struct mm_region* region = region_add(regions, addr, end, proct);
+    struct mm_region* region =
+      region_create(addr, end, proct | (options & 0x1f));
     region->mfile = file;
     region->offset = offset;
 
+    region_add(regions, region);
+
     u32_t attr = PG_ALLOW_USER;
     if ((proct & REGION_WRITE)) {
         attr |= PG_WRITE;
@@ -61,7 +64,7 @@ found:
 }
 
 void*
-mem_unmap(ptr_t mnt, struct llist_header* regions, void* addr, size_t length)
+mem_unmap(ptr_t mnt, vm_regions_t* regions, void* addr, size_t length)
 {
     length = ROUNDUP(length, PG_SIZE);
     ptr_t cur_addr = ROUNDDOWN((ptr_t)addr, PG_SIZE);
@@ -69,7 +72,7 @@ mem_unmap(ptr_t mnt, struct llist_header* regions, void* addr, size_t length)
 
     llist_for_each(pos, n, regions, head)
     {
-        if (pos->start >= cur_addr) {
+        if (pos->start <= cur_addr) {
             break;
         }
     }
@@ -87,6 +90,9 @@ mem_unmap(ptr_t mnt, struct llist_header* regions, void* addr, size_t length)
             l = length;
         }
 
+        // TODO for shared mappings, sync page content if modified. (also
+        // implement msync)
+
         for (size_t i = 0; i < l; i += PG_SIZE) {
             ptr_t pa = vmm_del_mapping(mnt, cur_addr + i);
             if (pa) {
@@ -106,19 +112,13 @@ mem_unmap(ptr_t mnt, struct llist_header* regions, void* addr, size_t length)
     }
 }
 
-__DEFINE_LXSYSCALL5(void*,
-                    mmap,
-                    void*,
-                    addr,
-                    size_t,
-                    length,
-                    int,
-                    proct,
-                    int,
-                    fd,
-                    size_t,
-                    offset)
+__DEFINE_LXSYSCALL3(void*, sys_mmap, void*, addr, size_t, length, va_list, lst)
 {
+    int proct = va_arg(lst, int);
+    int fd = va_arg(lst, u32_t);
+    off_t offset = va_arg(lst, off_t);
+    int options = va_arg(lst, int);
+
     int errno = 0;
     struct v_fd* vfd;
     if ((errno = vfs_getfd(fd, &vfd))) {
@@ -126,13 +126,16 @@ __DEFINE_LXSYSCALL5(void*,
         return (void*)-1;
     }
 
+    length = ROUNDUP(length, PG_SIZE);
+
     return mem_map(PD_REFERENCED,
                    &__current->mm.regions,
                    addr,
                    vfd->file,
                    offset,
                    length,
-                   proct);
+                   proct,
+                   options);
 }
 
 __DEFINE_LXSYSCALL2(void, munmap, void*, addr, size_t, length)
index 0e0982d7d2d9b0915ed6065c7fb90deb79c000e0..59dd6e3c330c5570e8d3d8f49618d2abaab92719 100644 (file)
@@ -1,35 +1,40 @@
 #include <lunaix/mm/region.h>
 #include <lunaix/mm/valloc.h>
 
+#include <klibc/string.h>
+
 struct mm_region*
-region_add(struct llist_header* lead,
-           unsigned long start,
-           unsigned long end,
-           unsigned int attr)
+region_create(ptr_t start, ptr_t end, u32_t attr)
 {
-    struct mm_region* region = valloc(sizeof(struct mm_region));
-
-    *region = (struct mm_region){ .attr = attr, .end = end, .start = start };
+    return valloc(sizeof(struct mm_region));
+}
 
+void
+region_add(vm_regions_t* lead, struct mm_region* vmregion)
+{
     if (llist_empty(lead)) {
-        llist_append(lead, &region->head);
-        return region;
+        llist_append(lead, &vmregion->head);
+        return vmregion;
     }
 
-    struct mm_region *pos, *n;
-    llist_for_each(pos, n, lead, head)
-    {
-        if (start >= pos->end && end <= n->start) {
+    ptr_t cur_end = 0;
+    struct mm_region *pos = (struct mm_region*)lead,
+                     *n = list_entry(lead->next, struct mm_region, head);
+    do {
+        if (vmregion->start >= cur_end && vmregion->end <= n->start) {
             break;
         }
-    }
+        cur_end = n->end;
+        pos = n;
+        n = list_entry(n->head.next, struct mm_region, head);
+    } while ((ptr_t)&pos->head != (ptr_t)lead);
 
-    llist_insert_after(&pos->head, &region->head);
-    return region;
+    // XXX caution. require mm_region::head to be the lead of struct
+    llist_insert_after(&pos->head, &vmregion->head);
 }
 
 void
-region_release_all(struct llist_header* lead)
+region_release_all(vm_regions_t* lead)
 {
     struct mm_region *pos, *n;
 
@@ -40,22 +45,24 @@ region_release_all(struct llist_header* lead)
 }
 
 void
-region_copy(struct llist_header* src, struct llist_header* dest)
+region_copy(vm_regions_t* src, vm_regions_t* dest)
 {
     if (!src) {
         return;
     }
 
-    struct mm_region *pos, *n;
+    struct mm_region *pos, *n, *dup;
 
     llist_for_each(pos, n, src, head)
     {
-        region_add(dest, pos->start, pos->end, pos->attr);
+        dup = valloc(sizeof(struct mm_region));
+        memcpy(dup, pos, sizeof(*pos));
+        region_add(dest, dup);
     }
 }
 
 struct mm_region*
-region_get(struct llist_header* lead, unsigned long vaddr)
+region_get(vm_regions_t* lead, unsigned long vaddr)
 {
     if (llist_empty(lead)) {
         return NULL;
index 8df3f2c9ef8090422000c7dbf60116220730ccbe..9cef1f87ac40a70a7b9502607187a4d2fba1de57 100644 (file)
@@ -142,9 +142,12 @@ init_proc_user_space(struct proc_info* pcb)
 
     /*---  分配用户栈  ---*/
 
+    struct mm_region* stack_vm;
+
+    stack_vm = region_create(
+      USTACK_END, USTACK_TOP, REGION_RW | REGION_RSHARED | REGION_ANON);
     // 注册用户栈区域
-    region_add(
-      &pcb->mm.regions, USTACK_END, USTACK_TOP, REGION_RW | REGION_RSHARED);
+    region_add(&pcb->mm.regions, stack_vm);
 
     // 预留地址空间,具体物理页将由Page Fault Handler按需分配。
     for (uintptr_t i = PG_ALIGN(USTACK_END); i < USTACK_TOP; i += PG_SIZE) {
index d2196166b6b2bfc37ced58f303dbe31a15d2e490..46500608a3da9a913dd459e16f4b8ab8ca37d9eb 100644 (file)
@@ -400,6 +400,7 @@ destroy_process(pid_t pid)
     vfree(proc->fdtable);
     vfree_dma(proc->fxstate);
 
+    // TODO unmap all regions
     struct mm_region *pos, *n;
     llist_for_each(pos, n, &proc->mm.regions, head)
     {
index 4610acf2b9969d4ccfd77752e324a1f708bb8a9e..7c954b30ea9c3a44510885d0e389dbd8de379c05 100644 (file)
@@ -1,4 +1,5 @@
 #include <lunaix/fs/taskfs.h>
+#include <lunaix/process.h>
 
 void
 __read_pending_sig(struct twimap* map)
diff --git a/lunaix-os/usr/api/mann.c b/lunaix-os/usr/api/mann.c
new file mode 100644 (file)
index 0000000..3c167a3
--- /dev/null
@@ -0,0 +1,12 @@
+#include <lunaix/syscall.h>
+#include <usr/sys/mann.h>
+
+__LXSYSCALL2_VARG(void*, sys_mmap, void*, addr, size_t, length);
+
+void*
+mmap(void* addr, size_t length, int proct, int flags, int fd, off_t offset)
+{
+    return sys_mmap(addr, length, proct, fd, offset, flags);
+}
+
+__LXSYSCALL2(void, munmap, void*, addr, size_t, length)