From 642855f81fd03b9fd6540ac99c665b57b4b38cc8 Mon Sep 17 00:00:00 2001 From: Minep Date: Wed, 28 Dec 2022 23:19:19 +0000 Subject: [PATCH 1/1] regression: mmap for fd 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. --- lunaix-os/arch/x86/boot.S | 2 +- lunaix-os/includes/lunaix/fctrl.h | 2 +- lunaix-os/includes/lunaix/fs.h | 4 -- lunaix-os/includes/lunaix/mm/mm.h | 17 ++++---- lunaix-os/includes/lunaix/mm/mmap.h | 10 +++-- lunaix-os/includes/lunaix/mm/page.h | 1 + lunaix-os/includes/lunaix/mm/region.h | 13 ++++-- lunaix-os/includes/lunaix/process.h | 3 +- lunaix-os/includes/lunaix/syscall.h | 9 ++--- lunaix-os/includes/lunaix/syscall_utils.h | 10 +++++ lunaix-os/includes/lunaix/types.h | 4 +- lunaix-os/includes/usr/sys/mann.h | 13 ++++++ lunaix-os/includes/usr/sys/mann_flags.h | 24 +++++++++++ lunaix-os/includes/usr/sys/types.h | 12 ++++++ lunaix-os/kernel/asm/x86/pfault.c | 49 ++++++++++++----------- lunaix-os/kernel/asm/x86/syscall.S | 9 ++--- lunaix-os/kernel/demos/dir_read.c | 2 +- lunaix-os/kernel/demos/simple_sh.c | 28 ++++++++++++- lunaix-os/kernel/device/device.c | 1 + lunaix-os/kernel/fs/mount.c | 1 + lunaix-os/kernel/fs/path_walk.c | 1 + lunaix-os/kernel/fs/vfs.c | 3 +- lunaix-os/kernel/fs/xattr.c | 4 ++ lunaix-os/kernel/mm/mmap.c | 43 +++++++++++--------- lunaix-os/kernel/mm/region.c | 49 +++++++++++++---------- lunaix-os/kernel/process/process.c | 7 +++- lunaix-os/kernel/process/sched.c | 1 + lunaix-os/kernel/process/task_attr.c | 1 + lunaix-os/usr/api/mann.c | 12 ++++++ 29 files changed, 231 insertions(+), 104 deletions(-) create mode 100644 lunaix-os/includes/lunaix/syscall_utils.h create mode 100644 lunaix-os/includes/usr/sys/mann.h create mode 100644 lunaix-os/includes/usr/sys/mann_flags.h create mode 100644 lunaix-os/includes/usr/sys/types.h create mode 100644 lunaix-os/usr/api/mann.c diff --git a/lunaix-os/arch/x86/boot.S b/lunaix-os/arch/x86/boot.S index 9e44437..d1d14ba 100644 --- a/lunaix-os/arch/x86/boot.S +++ b/lunaix-os/arch/x86/boot.S @@ -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 diff --git a/lunaix-os/includes/lunaix/fctrl.h b/lunaix-os/includes/lunaix/fctrl.h index 5ec0eef..36efb4b 100644 --- a/lunaix-os/includes/lunaix/fctrl.h +++ b/lunaix-os/includes/lunaix/fctrl.h @@ -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, diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index 3ec85f5..59faabc 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -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) \ diff --git a/lunaix-os/includes/lunaix/mm/mm.h b/lunaix-os/includes/lunaix/mm/mm.h index 07d3d79..5890f61 100644 --- a/lunaix-os/includes/lunaix/mm/mm.h +++ b/lunaix-os/includes/lunaix/mm/mm.h @@ -6,6 +6,8 @@ #include #include +#include + 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; diff --git a/lunaix-os/includes/lunaix/mm/mmap.h b/lunaix-os/includes/lunaix/mm/mmap.h index 78c12d6..333504a 100644 --- a/lunaix-os/includes/lunaix/mm/mmap.h +++ b/lunaix-os/includes/lunaix/mm/mmap.h @@ -2,18 +2,20 @@ #define __LUNAIX_MMAP_H #include +#include #include 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 */ diff --git a/lunaix-os/includes/lunaix/mm/page.h b/lunaix-os/includes/lunaix/mm/page.h index 37496a3..8d479c2 100644 --- a/lunaix-os/includes/lunaix/mm/page.h +++ b/lunaix-os/includes/lunaix/mm/page.h @@ -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)) diff --git a/lunaix-os/includes/lunaix/mm/region.h b/lunaix-os/includes/lunaix/mm/region.h index c1c8074..be4a300 100644 --- a/lunaix-os/includes/lunaix/mm/region.h +++ b/lunaix-os/includes/lunaix/mm/region.h @@ -3,16 +3,21 @@ #include +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 */ diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index 1eacf12..ab5dde9 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,7 @@ struct proc_mm { heap_context_t u_heap; - struct llist_header regions; + vm_regions_t regions; }; struct proc_sigstate diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h index 04ae40b..8da4dc5 100644 --- a/lunaix-os/includes/lunaix/syscall.h +++ b/lunaix-os/includes/lunaix/syscall.h @@ -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 index 0000000..fcc7dc3 --- /dev/null +++ b/lunaix-os/includes/lunaix/syscall_utils.h @@ -0,0 +1,10 @@ +#ifndef __LUNAIX_SYSCALL_UTILS_H +#define __LUNAIX_SYSCALL_UTILS_H + +#include +#include + +#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 */ diff --git a/lunaix-os/includes/lunaix/types.h b/lunaix-os/includes/lunaix/types.h index f99620f..0d1ad19 100644 --- a/lunaix-os/includes/lunaix/types.h +++ b/lunaix-os/includes/lunaix/types.h @@ -2,8 +2,8 @@ #define __LUNAIX_TYPES_H #include -#include #include +#include #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 index 0000000..140ef35 --- /dev/null +++ b/lunaix-os/includes/usr/sys/mann.h @@ -0,0 +1,13 @@ +#ifndef __LUNAIX_SYS_MANN_H +#define __LUNAIX_SYS_MANN_H + +#include +#include + +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 index 0000000..3168d63 --- /dev/null +++ b/lunaix-os/includes/usr/sys/mann_flags.h @@ -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 index 0000000..712d687 --- /dev/null +++ b/lunaix-os/includes/usr/sys/types.h @@ -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 */ diff --git a/lunaix-os/kernel/asm/x86/pfault.c b/lunaix-os/kernel/asm/x86/pfault.c index 6498619..bbaf59f 100644 --- a/lunaix-os/kernel/asm/x86/pfault.c +++ b/lunaix-os/kernel/asm/x86/pfault.c @@ -9,6 +9,8 @@ #include #include +#include + 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) ; diff --git a/lunaix-os/kernel/asm/x86/syscall.S b/lunaix-os/kernel/asm/x86/syscall.S index bd51976..eb16783 100644 --- a/lunaix-os/kernel/asm/x86/syscall.S +++ b/lunaix-os/kernel/asm/x86/syscall.S @@ -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 diff --git a/lunaix-os/kernel/demos/dir_read.c b/lunaix-os/kernel/demos/dir_read.c index e1ef7a2..70070a1 100644 --- a/lunaix-os/kernel/demos/dir_read.c +++ b/lunaix-os/kernel/demos/dir_read.c @@ -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); } diff --git a/lunaix-os/kernel/demos/simple_sh.c b/lunaix-os/kernel/demos/simple_sh.c index acebe21..8bb357b 100644 --- a/lunaix-os/kernel/demos/simple_sh.c +++ b/lunaix-os/kernel/demos/simple_sh.c @@ -6,6 +6,8 @@ #include #include +#include + #include #include @@ -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; diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c index b784fdb..3647f10 100644 --- a/lunaix-os/kernel/device/device.c +++ b/lunaix-os/kernel/device/device.c @@ -6,6 +6,7 @@ #include #include #include +#include static DEFINE_LLIST(root_list); diff --git a/lunaix-os/kernel/fs/mount.c b/lunaix-os/kernel/fs/mount.c index 7db9513..12e1d4b 100644 --- a/lunaix-os/kernel/fs/mount.c +++ b/lunaix-os/kernel/fs/mount.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include diff --git a/lunaix-os/kernel/fs/path_walk.c b/lunaix-os/kernel/fs/path_walk.c index a0331e7..cd0ac01 100644 --- a/lunaix-os/kernel/fs/path_walk.c +++ b/lunaix-os/kernel/fs/path_walk.c @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 9680f2e..cbe3c39 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -53,6 +53,7 @@ #include #include #include +#include #include @@ -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; diff --git a/lunaix-os/kernel/fs/xattr.c b/lunaix-os/kernel/fs/xattr.c index 94f85b7..6fdb300 100644 --- a/lunaix-os/kernel/fs/xattr.c +++ b/lunaix-os/kernel/fs/xattr.c @@ -1,7 +1,11 @@ #include #include #include +#include #include +#include + +#define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno) struct v_xattr_entry* xattr_new(struct hstr* name) diff --git a/lunaix-os/kernel/mm/mmap.c b/lunaix-os/kernel/mm/mmap.c index 8eb6b20..7b8ce8f 100644 --- a/lunaix-os/kernel/mm/mmap.c +++ b/lunaix-os/kernel/mm/mmap.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -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) diff --git a/lunaix-os/kernel/mm/region.c b/lunaix-os/kernel/mm/region.c index 0e0982d..59dd6e3 100644 --- a/lunaix-os/kernel/mm/region.c +++ b/lunaix-os/kernel/mm/region.c @@ -1,35 +1,40 @@ #include #include +#include + 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, ®ion->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, ®ion->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; diff --git a/lunaix-os/kernel/process/process.c b/lunaix-os/kernel/process/process.c index 8df3f2c..9cef1f8 100644 --- a/lunaix-os/kernel/process/process.c +++ b/lunaix-os/kernel/process/process.c @@ -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) { diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index d219616..4650060 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -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) { diff --git a/lunaix-os/kernel/process/task_attr.c b/lunaix-os/kernel/process/task_attr.c index 4610acf..7c954b3 100644 --- a/lunaix-os/kernel/process/task_attr.c +++ b/lunaix-os/kernel/process/task_attr.c @@ -1,4 +1,5 @@ #include +#include 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 index 0000000..3c167a3 --- /dev/null +++ b/lunaix-os/usr/api/mann.c @@ -0,0 +1,12 @@ +#include +#include + +__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) -- 2.27.0