From 813ab0060cfbe5651423f9d92c1e7384769606e3 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sat, 22 Oct 2022 10:58:43 -0300 Subject: [PATCH] file mapping stub --- src/fs/vfs.c | 17 +++++++++++ src/include/kernel/devman.h | 2 ++ src/include/kernel/vfs.h | 1 + src/include/kernel/vmm.h | 2 ++ src/sys/devman.c | 12 ++++++++ src/sys/mm/vmm.c | 24 +++++++++++++++ src/sys/syscalls/mmap.c | 60 +++++++++++++++++++++++++++---------- src/video/framebuffer.c | 30 ++++++++++++++++++- 8 files changed, 131 insertions(+), 17 deletions(-) diff --git a/src/fs/vfs.c b/src/fs/vfs.c index 5ec0367c..90095df1 100644 --- a/src/fs/vfs.c +++ b/src/fs/vfs.c @@ -237,6 +237,23 @@ int vfs_open(vnode_t** buff, dirnode_t* ref, char* path){ } +int vfs_map(vnode_t* node, void* addr, size_t len, size_t offset, size_t mmuflags){ + + spinlock_acquire(&lock); + + int err; + + if(GETTYPE(node->st.st_mode) == TYPE_CHARDEV){ + err = devman_map(node->st.st_rdev, addr, len, offset, mmuflags); + } + else _panic("Normal file mapping not supported!", 0); + + spinlock_release(&lock); + + return err; + +} + int vfs_create(dirnode_t* ref, char* path, mode_t mode){ dirnode_t* parent = NULL; diff --git a/src/include/kernel/devman.h b/src/include/kernel/devman.h index a3cfadc7..942fc759 100644 --- a/src/include/kernel/devman.h +++ b/src/include/kernel/devman.h @@ -18,6 +18,7 @@ typedef struct{ int (*isseekable)(int minor, size_t* seekmax); int (*ioctl)(int minor, unsigned long request, void* arg, int* result); int (*poll)(int minor, pollfd* fd); + int (*map)(int minor, void* addr, size_t len, size_t offset, size_t mmuflags); } devcalls; int devman_read(int *error, int dev, void* buff, size_t count, size_t offset); @@ -27,6 +28,7 @@ int devman_isatty(int dev); int devman_isseekable(int dev, size_t* seekmax); int devman_ioctl(int dev, unsigned long request, void* arg, int* result); int devman_poll(int dev, pollfd* fd); +int devman_map(int dev, void* addr, size_t len, size_t offset, size_t mmuflags); void devman_init(); #endif diff --git a/src/include/kernel/vfs.h b/src/include/kernel/vfs.h index 42d8cad1..378c26d8 100644 --- a/src/include/kernel/vfs.h +++ b/src/include/kernel/vfs.h @@ -90,6 +90,7 @@ int vfs_poll(vnode_t* node, pollfd* fd); int vfs_chmod(vnode_t* node, mode_t mode); int vfs_symlink(dirnode_t* ref, char* path, char* target, mode_t mode); int vfs_link(dirnode_t* ref, vnode_t* link, char* path); +int vfs_map(vnode_t* node, void* addr, size_t len, size_t offset, size_t mmuflags); void vfs_init(); dirnode_t* vfs_root(); diff --git a/src/include/kernel/vmm.h b/src/include/kernel/vmm.h index e9da8770..b9f7acb4 100644 --- a/src/include/kernel/vmm.h +++ b/src/include/kernel/vmm.h @@ -1,6 +1,7 @@ #ifndef _VMM_H_INCLUDE #define _VMM_H_INCLUDE +#include #include #include #include @@ -64,6 +65,7 @@ void* vmm_alloc(size_t pagec, size_t mmuflags); bool vmm_setfree(void* addr, size_t pagec); bool vmm_allocnowat(void* addr, size_t mmuflags, size_t size); void* vmm_allocfrom(void* addr, size_t mmuflags, size_t size); +int vmm_mapfile(vnode_t* node, void* addr, size_t len, size_t offset, size_t mmuflags); vmm_context* vmm_newcontext(); void vmm_switchcontext(vmm_context*); int vmm_fork(vmm_context* oldctx, vmm_context* newctx); diff --git a/src/sys/devman.c b/src/sys/devman.c index df649684..422dcead 100644 --- a/src/sys/devman.c +++ b/src/sys/devman.c @@ -85,6 +85,18 @@ int devman_poll(int dev, pollfd* fd){ return majorcalls[major(dev)]->poll(minor(dev), fd); } +int devman_map(int dev, void* addr, size_t len, size_t offset, size_t mmuflags){ + + if(major(dev) > highestmajor) + return ENOTTY; + + if(!majorcalls[major(dev)]->map) + return ENOTTY; + + return majorcalls[major(dev)]->map(minor(dev), addr, len, offset, mmuflags); + +} + void devman_init(){ devfs_init(); diff --git a/src/sys/mm/vmm.c b/src/sys/mm/vmm.c index e4d62ad0..6d26c116 100644 --- a/src/sys/mm/vmm.c +++ b/src/sys/mm/vmm.c @@ -551,6 +551,30 @@ bool vmm_setfree(void* addr, size_t pagec){ return result; } +int vmm_mapfile(vnode_t* node, void* addr, size_t len, size_t offset, size_t mmuflags){ + + int* lock; + vmm_mapping** start; + + getcontextinfo(addr, &lock, &start); + + spinlock_acquire(lock); + + int err = 0; + + if(!setmap(start, addr, len, mmuflags, VMM_TYPE_FILE, node, offset)) + err = ENOMEM; + + if(err == 0) + err = vfs_map(node, addr, len, offset, mmuflags); + + spinlock_release(lock); + + return err; + + +} + bool vmm_map(void* paddr, void* vaddr, size_t pagec, size_t mmuflags){ int* lock; vmm_mapping** start; diff --git a/src/sys/syscalls/mmap.c b/src/sys/syscalls/mmap.c index ff653146..a5f515ec 100644 --- a/src/sys/syscalls/mmap.c +++ b/src/sys/syscalls/mmap.c @@ -2,6 +2,7 @@ #include #include #include +#include // linux abi @@ -44,7 +45,7 @@ #define MFD_CLOEXEC 1U #define MFD_ALLOW_SEALING 2U -syscallret syscall_mmap(void* hint, size_t len, int prot, int flags, int fd, off_t offset){ +syscallret syscall_mmap(void* hint, size_t len, int prot, int flags, int ifd, off_t offset){ syscallret retv; @@ -55,12 +56,6 @@ syscallret syscall_mmap(void* hint, size_t len, int prot, int flags, int fd, off retv.errno = EINVAL; return retv; } - - if((flags & (MAP_ANON | MAP_PRIVATE)) != (MAP_ANON | MAP_PRIVATE)){ - retv.errno = ENOSYS; - return retv; - - } size_t mmuflags = 0; @@ -79,17 +74,50 @@ syscallret syscall_mmap(void* hint, size_t len, int prot, int flags, int fd, off void* ret = NULL; - if(hint) - ret = vmm_allocnowat(hint, mmuflags, len) ? hint : NULL; // TODO demand page - if(ret == NULL && (flags & MAP_FIXED) == 0) + if(flags & MAP_ANON){ + + if(hint) + ret = vmm_allocnowat(hint, mmuflags, len) ? hint : NULL; // TODO demand page + if(ret == NULL && (flags & MAP_FIXED) == 0) + ret = vmm_allocfrom(USER_ALLOC_START, mmuflags, plen); + + if(!ret) + retv.errno = ENOMEM; + else{ + retv.ret = ret; + if(hint && (flags & MAP_ANON)) + memset(ret, 0, plen*PAGE_SIZE); + } + } + else{ + + // open node + + proc_t* proc = arch_getcls()->thread->proc; + + fd_t* fd; + + retv.errno = fd_access(&proc->fdtable, &fd, ifd); + + if(retv.errno) + return retv; + + + if(hint) + _panic("mmap: file hint unimplemented", 0); + ret = vmm_allocfrom(USER_ALLOC_START, mmuflags, plen); - if(!ret) - retv.errno = ENOMEM; - else{ - retv.ret = ret; - if(hint && (flags & MAP_ANON)) - memset(ret, 0, plen*PAGE_SIZE); + if(!ret) + retv.errno = ENOMEM; + else{ + retv.errno = vmm_mapfile(fd->node, ret, plen, offset, mmuflags); + if(!retv.errno) + retv.ret = ret; + } + + fd_release(fd); + } return retv; diff --git a/src/video/framebuffer.c b/src/video/framebuffer.c index 71b5eb04..fee464e5 100644 --- a/src/video/framebuffer.c +++ b/src/video/framebuffer.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include static volatile struct limine_framebuffer_request fbreq = { .id = LIMINE_FRAMEBUFFER_REQUEST, @@ -71,6 +73,7 @@ static int isseekable(int minor, size_t* max){ } #define FBIOGET_VSCREENINFO 0x4600 +#define FBIOPUT_VSCREENINFO 0x4601 #define FBIOGET_FSCREENINFO 0x4602 struct fb_bitfield { @@ -140,6 +143,8 @@ static int ioctl(int minor, unsigned long req, void* arg){ struct limine_framebuffer* fb = fbs[minor]; switch(req){ + case FBIOPUT_VSCREENINFO: // TODO maybe this should be done properly + break; case FBIOGET_FSCREENINFO: { fb_fix_screeninfo* i = arg; @@ -205,11 +210,34 @@ static int ioctl(int minor, unsigned long req, void* arg){ } +static map(int minor, void* addr, size_t len, size_t offset, size_t mmuflags){ + + int properlen = len*PAGE_SIZE; + + int err = devchecks(minor, &properlen, offset); + + properlen /= PAGE_SIZE; + + if(properlen % PAGE_SIZE) + ++properlen; + + if(err) + return err; + + for(uintmax_t page = 0; page < len; ++page){ + if(page < properlen) + arch_mmu_map(arch_getcls()->context->context, fbs[minor]->address + offset, addr, mmuflags); + + } + + return 0; +} static devcalls calls = { - read, write, isatty, isseekable, ioctl + read, write, isatty, isseekable, ioctl, NULL, map }; + void fb_init(){ if(!fbreq.response)