Advertisement
iocoder

pmem.c

Jan 17th, 2013
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.37 KB | None | 0 0
  1. /*
  2.       +----------------------------------------------------------+
  3.       | +------------------------------------------------------+ |
  4.       | |  Quafios Kernel 1.0.1.                   | |
  5.       | |  -> Physical Memory Manager.             | |
  6.       | +------------------------------------------------------+ |
  7.       +----------------------------------------------------------+
  8. */
  9.  
  10. // This file is part of Quafios 1.0.1 source code.
  11. // Copyright (C) 2012  Mostafa Abd El-Aziz Mohamed.
  12.  
  13. // This program is free software: you can redistribute it and/or modify
  14. // it under the terms of the GNU General Public License as published by
  15. // the Free Software Foundation, either version 3 of the License, or
  16. // (at your option) any later version.
  17.  
  18. // This program is distributed in the hope that it will be useful,
  19. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. // GNU General Public License for more details.
  22.  
  23. // You should have received a copy of the GNU General Public License
  24. // along with Quafios.  If not, see <http://www.gnu.org/licenses/>.
  25.  
  26. // Visit http://www.quafios.com/ for contact information.
  27.  
  28. /* pmem.c
  29.  * Physical Memory Management Unit.
  30.  * I have no idea what i am doing here -_-'
  31.  */
  32.  
  33. unsigned int  pmem_usable_pages = 0;
  34. unsigned int  ram_size = 0;
  35.  
  36. // 4MB memory map:
  37. unsigned int pmmap[MEMORY_PAGES];
  38.  
  39. // Free page list:
  40. linkedlist pfreelist;
  41.  
  42. // a kernel page for physical memory IO:
  43. unsigned char physical_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
  44. unsigned int cur_physical_page = NULLPTR;
  45.  
  46. /* Access physical memory routine */
  47. unsigned char pmem_readb(void *p_addr) {
  48.    
  49.     // p_addr: physical memory address which is to be accessed.
  50.    
  51.     // At boot time, kernel appears at linear base address
  52.     // 0xC0000000, the space from 0x00000000 to 0xBFFFFFFF
  53.     // is not mapped to any physical memory region. Thus,
  54.     // Quafios kernel can not access anything in memory
  55.     // except itself. Unfortunately, many data structures,
  56.     // like the multiboot info structure (mbi), reside outside
  57.     // the kernel... somewhere in physical memory referred
  58.     // to by physical address pointers. Our mission is to re-map
  59.     // physical_page so that it refers to the physical page
  60.     // where p_addr refers.
  61.    
  62.     // p_addr = p_page (page base) + p_off (offset to that base).
  63.     unsigned int p_page = ((unsigned int) p_addr) & PAGE_BASE_MASK;
  64.     unsigned int p_off  = ((unsigned int) p_addr) & (PAGE_SIZE-1);
  65.    
  66.     if (p_page != cur_physical_page)
  67.         kmap((unsigned int) physical_page, cur_physical_page=p_page);
  68.    
  69.     return physical_page[p_off];
  70. }
  71.  
  72. unsigned short pmem_readw(void *p_addr) {
  73.     return   (pmem_readb(p_addr+0)<< 0)
  74.            + (pmem_readb(p_addr+1)<< 8);
  75. }
  76.  
  77. unsigned int pmem_readl(void *p_addr) {
  78.     return   (pmem_readb(p_addr+0)<< 0)
  79.            + (pmem_readb(p_addr+1)<< 8)
  80.            + (pmem_readb(p_addr+2)<<16)
  81.            + (pmem_readb(p_addr+3)<<24);
  82. }
  83.  
  84. void *ppalloc() {
  85.  
  86.     unsigned int eflags = get_eflags();
  87.     cli();
  88.  
  89.     if (!pfreelist.count) {
  90.         set_eflags(eflags);
  91.         return (void *) NULLPTR;
  92.     }
  93.  
  94.     linknode *entry = pfreelist.first;
  95.     linkedlist_remove(&pfreelist, pfreelist.first, NULLNODE);
  96.  
  97.     set_eflags(eflags);
  98.     return (void *)((((unsigned int) entry) - ((unsigned int) &pmmap))*1024);
  99. }
  100.  
  101.  
  102. void ppfree(void *base) {
  103.  
  104.     unsigned int eflags = get_eflags();
  105.     cli();
  106.  
  107.     linknode *entry = (linknode *) ((unsigned int) &pmmap[((unsigned int)base)/PAGE_SIZE]);
  108.     linkedlist_add(&pfreelist, entry);
  109.  
  110.     set_eflags(eflags);
  111.     return;
  112. }
  113.  
  114. void pmem_init() {
  115.  
  116.     // The multi-boot compliant boot loader which loads Quafios
  117.     // should provide Quafios kernel with a valid "memory map".
  118.     // In PC, for example, the boot loader shall read the memory
  119.     // map from BIOS then pass it to the kernel during boot process.
  120.     // The code below process this memory map and initializes
  121.     // the "pfreelist" linkedlist according to that map.
  122.  
  123.     // Make sure the boot info struct is supplied with memory map:
  124.     if (!(pmem_readl(&(mbi->flags)) & MULTIBOOT_INFO_MEM_MAP))
  125.         idle();
  126.  
  127.     // Initialize pfreelist:
  128.     linkedlist_init(&pfreelist);
  129.  
  130.     // Traverse over the memory map, and set RAM Regions as free:
  131.     unsigned int mmap_start  = pmem_readl(&(mbi->mmap_addr));
  132.     unsigned int mmap_length = pmem_readl(&(mbi->mmap_length));
  133.  
  134.     unsigned int i = mmap_start;
  135.     while (i < mmap_start + mmap_length) {
  136.    
  137.         // Scan a memory map entry.
  138.         multiboot_memory_map_t *mbmm = (multiboot_memory_map_t *) i;
  139.         unsigned int size = pmem_readl(&(mbmm->size));
  140.         unsigned int addr = pmem_readl(&(mbmm->addr));
  141.         unsigned int len  = pmem_readl(&(mbmm->len ));
  142.         unsigned int type = pmem_readl(&(mbmm->type));
  143.  
  144.         // update the pointer.
  145.         i += size + sizeof(mbmm->size);
  146.        
  147.         // skip if the region is not RAM:
  148.         if (type != MULTIBOOT_MEMORY_AVAILABLE) continue;
  149.  
  150.         // update ram size:
  151.         ram_size = addr + len;
  152.  
  153.         // Align to 4KB Boundary:
  154.         if (addr & (PAGE_SIZE-1)) {
  155.             len -= PAGE_SIZE-(addr&(PAGE_SIZE-1));
  156.             addr = (addr & PAGE_BASE_MASK) + PAGE_SIZE;
  157.         }
  158.  
  159.         unsigned int j = 0;
  160.         while(j < len/PAGE_SIZE) {
  161.             unsigned int frame = (addr/PAGE_SIZE) + j++;
  162.             unsigned int page = frame * PAGE_SIZE;
  163.  
  164.             if (page < KERNEL_PHYSICAL_START ||
  165.                 page > KERNEL_PHYSICAL_END)
  166.                 // add the page to free list as long
  167.                 // as it is not a kernel page:
  168.                 linkedlist_addlast(&pfreelist,
  169.                         (linknode *) &pmmap[frame]);
  170.  
  171.             pmem_usable_pages++;
  172.         }
  173.     }
  174. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement