Advertisement
iocoder

kernel/mm/umem.c

Nov 22nd, 2014
215
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.57 KB | None | 0 0
  1. /*
  2.  *        +----------------------------------------------------------+
  3.  *        | +------------------------------------------------------+ |
  4.  *        | |  Quafios Kernel 1.0.2.                               | |
  5.  *        | |  -> memman: user memory.                             | |
  6.  *        | +------------------------------------------------------+ |
  7.  *        +----------------------------------------------------------+
  8.  *
  9.  * This file is part of Quafios 1.0.2 source code.
  10.  * Copyright (C) 2014  Mostafa Abd El-Aziz Mohamed.
  11.  *
  12.  * This program is free software: you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation, either version 3 of the License, or
  15.  * (at your option) any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with Quafios.  If not, see <http://www.gnu.org/licenses/>.
  24.  *
  25.  * Visit http://www.quafios.com/ for contact information.
  26.  *
  27.  */
  28.  
  29. #include <arch/type.h>
  30. #include <lib/linkedlist.h>
  31. #include <sys/error.h>
  32. #include <sys/mm.h>
  33. #include <sys/fs.h>
  34. #include <sys/scheduler.h>
  35. #include <arch/page.h>
  36.  
  37. int32_t umem_init(umem_t *umem) {
  38.  
  39.     /* This function is called on creating a new process :D
  40.      * every process has a virtual memory... the struct
  41.      * umem_t holds data that describes the vmem.
  42.      */
  43.  
  44.     /* initialize heap: */
  45.     umem->heap_start = 0;
  46.     umem->brk_addr   = 0;
  47.     umem->heap_end   = 0;
  48.  
  49.     /* initialize arch-dependant stuff; */
  50.     return arch_vminit(umem);
  51.  
  52. }
  53.  
  54. int32_t umem_copy(umem_t *src, umem_t *dest) {
  55.  
  56.     /* used by fork() to copy src into dest. */
  57.     uint32_t i, j;
  58.     uint8_t *buf1, *buf2;
  59.  
  60.     buf1 = (uint8_t *) kmalloc(PAGE_SIZE);
  61.     if (buf1 == NULL)
  62.         return ENOMEM;
  63.  
  64.     buf2 = (uint8_t *) kmalloc(PAGE_SIZE);
  65.     if (buf2 == NULL) {
  66.         kfree(buf1);
  67.         return ENOMEM;
  68.     }
  69.  
  70.     /* copy umem; */
  71.     for (i=USER_MEMORY_BASE; i<KERNEL_MEMORY_BASE; i+=PAGE_DIR_SIZE) {
  72.  
  73.         if (!arch_vmdir_isMapped(src, i))
  74.             continue;
  75.  
  76.         for (j = i; j < i + PAGE_DIR_SIZE; j+=PAGE_SIZE) {
  77.             if (!arch_vmpage_isMapped(src, j))
  78.                 continue;
  79.             arch_vmpage_map(dest, (int32_t) j, 1 /* user mode */);
  80.             arch_vmpage_copy(src, j, dest, j, buf1, buf2);
  81.         }
  82.  
  83.     }
  84.  
  85.     /* free the buffers: */
  86.     kfree(buf1);
  87.     kfree(buf2);
  88.  
  89.     /* copy heap parameters: */
  90.     dest->heap_start = src->heap_start;
  91.     dest->brk_addr   = src->brk_addr;
  92.     dest->heap_end   = src->heap_end;
  93.  
  94.     /* done: */
  95.     return ESUCCESS;
  96.  
  97. }
  98.  
  99. void umem_free(umem_t *umem) {
  100.  
  101.     /* re-initialize heap: */
  102.     umem->heap_start = 0;
  103.     umem->brk_addr   = 0;
  104.     umem->heap_end   = 0;
  105.  
  106. }
  107.  
  108. uint32_t mmap(uint32_t base, uint32_t size, uint32_t type,
  109.               uint32_t flags, uint32_t fd, uint64_t off) {
  110.  
  111.     int32_t pages;
  112.     uint32_t addr;
  113.     umem_t *umem = &(curproc->umem); /* current process umem image. */
  114.  
  115.     /*printk("mmap called: %x, size: %x\n", base, size); */
  116.  
  117.     /* make sure fd is valid if a file is to be used */
  118.     if (type & MMAP_TYPE_FILE) {
  119.         if (fd < 0 || fd >= FD_MAX || curproc->file[fd] == NULL)
  120.             return 0;
  121.     }
  122.  
  123.     if (!base) {
  124.         /* allocate space */
  125.         base = umem->heap_end - size;
  126.     }
  127.  
  128.     size += base & (~PAGE_BASE_MASK);     /* rectify "size". */
  129.     base = base & PAGE_BASE_MASK;
  130.     pages = (size+PAGE_SIZE-1)/PAGE_SIZE; /* pages to be allocated. */
  131.     size = pages*PAGE_SIZE;               /* actual size. */
  132.  
  133.     /*printk("           - %x, size: %x\n", base, size); */
  134.  
  135.     /* make sure the system is initialized. */
  136.     if (curproc == NULL)
  137.         return 0; /* system is not initialized. */
  138.  
  139.     /* check whether the given range is valid or not. */
  140.     for (addr = base; addr < base + size; addr+=PAGE_SIZE) {
  141.         if (addr<USER_MEMORY_BASE || addr>=KERNEL_MEMORY_BASE) {
  142.             return 0; /* invalid */
  143.         }
  144.     }
  145.  
  146.     /* update heap end: */
  147.     if (base < umem->heap_end)
  148.         umem->heap_end = base;
  149.  
  150.     /* now allocate. */
  151.     for (addr = base; addr < base + size; addr+=PAGE_SIZE) {
  152.         arch_vmpage_map(umem, (int32_t) addr, 1 /* user mode */);
  153.         /* mapping a file? */
  154.         if (type & MMAP_TYPE_FILE) {
  155.             /* read file information */
  156.             file_t *file = curproc->file[fd];
  157.             inode_t *inode = file->inode;
  158.             file_mem_t *region = inode->sma.first;
  159.  
  160.             /* shared? */
  161.             if (flags & MMAP_FLAGS_SHARED) {
  162.                 /* search for the wanted region */
  163.                 while (region != NULL) {
  164.                     if (region->pos == off) {
  165.                         /* found */
  166.                         region->ref++;
  167.                         break;
  168.                     }
  169.                     region = region->next;
  170.                 }
  171.  
  172.                 /* region found or not? */
  173.                 if (!region) {
  174.                     /* region not found, create it */
  175.                     region = kmalloc(sizeof(file_mem_t));
  176.                     if (!region)
  177.                         return 0;
  178.                     if (file_reopen(file, &(region->file)))
  179.                         return 0;
  180.                     region->pos = off;
  181.                     region->paddr = 0;
  182.                     region->ref = 1;
  183.  
  184.                     /* add to the inode */
  185.                     linkedlist_add(&(inode->sma), region);
  186.                 }
  187.             } else {
  188.                 /* not shared, allocate a new one */
  189.                 region = kmalloc(sizeof(file_mem_t));
  190.                 if (!region)
  191.                     return 0;
  192.                 if (file_reopen(file, &(region->file)))
  193.                     return 0;
  194.                 region->pos = off;
  195.                 region->paddr = 0;
  196.                 region->ref = 0;
  197.             }
  198.             /* attach the virtual page to the mapping */
  199.             arch_vmpage_attach_file(umem, (int32_t) addr, region);
  200.             /* update offset */
  201.             off += PAGE_SIZE;
  202.         }
  203.     }
  204.  
  205.     /* return the base address. */
  206.     return base;
  207. }
  208.  
  209. int32_t munmap() {
  210.  
  211.  
  212. }
  213.  
  214. uint32_t brk(uint32_t addr) {
  215.  
  216.     /* change the value of break address. this increases
  217.      * or decreases data segment size.
  218.      */
  219.  
  220.     uint32_t first_page, last_page, i;
  221.  
  222.     /* receive umem structure of current process: */
  223.     umem_t *umem = &(curproc->umem);
  224.  
  225.     /* check limits: */
  226.     if (addr >= umem->heap_end || addr < umem->heap_start)
  227.         /* no memory :( */
  228.         return umem->brk_addr; /* just return current break. */
  229.  
  230.     /* compare addr with current break: */
  231.     if (addr > umem->brk_addr) {
  232.         /* move forward (map) */
  233.         first_page = (umem->brk_addr+PAGE_SIZE-1) & PAGE_BASE_MASK;
  234.         last_page  = (addr-1) & PAGE_BASE_MASK;
  235.         for (i = first_page; i <= last_page; i+=PAGE_SIZE)
  236.             arch_vmpage_map(umem, i, 1 /* user mode */);
  237.     } else if (addr < umem->brk_addr) {
  238.         /* move backwards (umap) */
  239.         first_page = (addr+PAGE_SIZE-1) & PAGE_BASE_MASK;
  240.         last_page  = (umem->brk_addr-1) & PAGE_BASE_MASK;
  241.         for (i = first_page; i <= last_page; i+=PAGE_SIZE)
  242.             arch_vmpage_unmap(umem, i);
  243.     }
  244.  
  245.     /* set & return the new break: */
  246.     return umem->brk_addr = addr;
  247.  
  248. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement