]> git.corax.cc Git - corax/commitdiff
kernel/arch: Add pg_dir_memset() function, enhance pg_dir_mmap() function to support...
authorMatthias Kruk <m@m10k.eu>
Mon, 4 May 2020 08:26:15 +0000 (17:26 +0900)
committerMatthias Kruk <m@m10k.eu>
Mon, 4 May 2020 08:26:15 +0000 (17:26 +0900)
kernel/arch/paging.c
kernel/include/arch.h

index 8e7d16e0a61530b54a91d1721c5987e0ed397383..99069e82a1f864b798d71cea944def7ef55733b8 100644 (file)
@@ -504,6 +504,68 @@ int pg_dir_memcpy(struct pagedir *ddir, void *dvaddr,
        return(ret_val);
 }
 
+int _pg_dir_memset(struct pagedir *ddir, void *dvaddr, int c, u32_t n)
+{
+       int ret_val;
+       u32_t dpaddr;
+       u32_t wsize;
+
+       ret_val = _pg_dir_vpxlate(ddir, (u32_t)dvaddr, (u32_t*)&dpaddr);
+
+       if(ret_val < 0) {
+               goto gtfo;
+       }
+
+       /*
+        * Calculate the number of bytes we can set without crossing
+        * page boundaries, writing into possibly unrelated pages.
+        */
+       ret_val = _pg_dir_pagesize(ddir, (u32_t)dvaddr, &wsize);
+
+       if(ret_val < 0) {
+               goto gtfo;
+       }
+
+       wsize = ALIGN((u32_t)dvaddr, wsize) - (u32_t)dvaddr;
+
+       memset((void*)dpaddr, c, wsize);
+       ret_val = (int)wsize;
+
+gtfo:
+       return(ret_val);
+}
+
+int pg_dir_memset(struct pagedir *ddir, void *dvaddr,
+                 int c, u32_t n)
+{
+       int ret_val;
+
+       ret_val = 0;
+
+       if(!ddir) {
+               /* kernel pagedir - just call memset() */
+               memset(dvaddr, c, n);
+               return((int)n);
+       }
+
+       while(n > 0) {
+               int set;
+
+               set = _pg_dir_memset(ddir, dvaddr, c, n);
+
+               if(set < 0) {
+                       ret_val = set;
+                       break;
+               }
+
+               dvaddr += set;
+               n -= set;
+               ret_val += set;
+       }
+
+       return(ret_val);
+}
+
 int _pg_dir_xfer(struct pagedir *ddir, void *dvaddr,
                                 struct pagedir *sdir, void *svaddr, u32_t bytes)
 {
@@ -1440,7 +1502,7 @@ int pg_dir_foreach_region(pg_dir_t *pd, int (*func)(pg_dir_t*, region_t*, void*)
 }
 
 static int _pg_dir_add_region(pg_dir_t *pd, void *base, u32_t size,
-                                                         u32_t type, u32_t attrs, u32_t flags)
+                             u32_t type, u32_t attrs, u32_t flags)
 {
        struct region *reg;
        int ret_val;
@@ -1622,48 +1684,65 @@ void pg_fault_debug(pg_dir_t *pdir, void *addr)
        return;
 }
 
-int pg_dir_mmap(pg_dir_t *pgdir, void *addr, u32_t size, int prot, int flags, void **dst)
+int pg_dir_mmap(pg_dir_t *pgdir, void *addr, u32_t size,
+               int prot, int flags, void **dst)
 {
        int ret_val;
 
        ret_val = -EINVAL;
 
        if(pgdir && dst) {
+               u32_t attrs;
+               u32_t rflags;
+               void* vaddr;
+               void* paddr;
+
                ret_val = -EFAULT;
 
                /* FIXME: Lock the page directory */
 
-               if(flags & MAP_PHYS) {
-                       u32_t attrs;
+               attrs = PAGE_ATTR_PRESENT;
 
-                       /* map the physical memory addr:size into the page directory */
-                       /* FIXME: Add another flag for identity mappings and otherwise map non-identically */
+               if(!(prot & PROT_EXEC)) {
+                       attrs |= PAGE_ATTR_NO_EXEC;
+               }
 
-                       attrs = PAGE_ATTR_PRESENT;
+               if(prot & PROT_WRITE) {
+                       attrs |= PAGE_ATTR_WRITABLE;
+               }
 
-                       if(!(prot & PROT_EXEC)) {
-                               attrs |= PAGE_ATTR_NO_EXEC;
-                       }
+               if(prot & PROT_READ) {
+                       attrs |= PAGE_ATTR_USER;
+               }
 
-                       if(prot & PROT_WRITE) {
-                               attrs |= PAGE_ATTR_WRITABLE;
-                       }
+               rflags = REGION_PRIV;
 
-                       if(prot & PROT_READ) {
-                               attrs |= PAGE_ATTR_USER;
-                       }
+               if(flags & MAP_PHYS) {
+                       /*
+                        * Map the physical memory addr:size into
+                        * the page directory
+                        */
 
-                       ret_val = pg_dir_map(pgdir, addr, addr, size, attrs);
+                       vaddr = addr;
+                       paddr = addr;
+                       rflags = REGION_SHARED;
+               }
 
-                       if(!ret_val) {
-                               /* also account for the new region */
-                               ret_val = _pg_dir_add_region(pgdir, addr, size,
-                                                                                        REGION_MMAP, 0, REGION_SHARED);
+               /*
+                * FIXME: Add another flag for identity mappings and
+                * otherwise map non-identically
+                */
+               ret_val = pg_dir_map(pgdir, paddr, vaddr, size, attrs);
 
-                               /* or unmap if it can't be accounted for */
-                               if(ret_val < 0) {
-                                       pg_dir_unmap(pgdir, addr, size);
-                               }
+               if(!ret_val) {
+                       /* also account for the new region */
+                       ret_val = _pg_dir_add_region(pgdir, addr, size,
+                                                    REGION_MMAP, 0,
+                                                    rflags);
+
+                       /* or unmap if it can't be accounted for */
+                       if(ret_val < 0) {
+                               pg_dir_unmap(pgdir, addr, size);
                        }
                }
 
index 4741ab29c70eb8a3d1f289f08721e2b0efa83b24..161fed50f0f053792c17659d8815be04f1a5770c 100644 (file)
@@ -237,6 +237,7 @@ void*   pg_dir_get_ustack(pg_dir_t*);
 void*   pg_dir_sbrk(pg_dir_t*, i32_t);
 int     pg_dir_foreach_region(pg_dir_t*, int(*)(pg_dir_t*, struct region*, void*), void*);
 int     pg_dir_memcpy(pg_dir_t*, void*, pg_dir_t*, void*, u32_t);
+int     pg_dir_memset(pg_dir_t*, void*, int, u32_t);
 int     pg_dir_mmap(pg_dir_t*, void*, u32_t, int, int, void**);
 int     pg_dir_munmap(pg_dir_t*, void*, u32_t);