Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- +----------------------------------------------------------+
- | +------------------------------------------------------+ |
- | | Quafios Kernel 1.0.1. | |
- | | -> Physical Memory Manager. | |
- | +------------------------------------------------------+ |
- +----------------------------------------------------------+
- */
- // This file is part of Quafios 1.0.1 source code.
- // Copyright (C) 2012 Mostafa Abd El-Aziz Mohamed.
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- // You should have received a copy of the GNU General Public License
- // along with Quafios. If not, see <http://www.gnu.org/licenses/>.
- // Visit http://www.quafios.com/ for contact information.
- /* pmem.c
- * Physical Memory Management Unit.
- * I have no idea what i am doing here -_-'
- */
- unsigned int pmem_usable_pages = 0;
- unsigned int ram_size = 0;
- // 4MB memory map:
- unsigned int pmmap[MEMORY_PAGES];
- // Free page list:
- linkedlist pfreelist;
- // a kernel page for physical memory IO:
- unsigned char physical_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
- unsigned int cur_physical_page = NULLPTR;
- /* Access physical memory routine */
- unsigned char pmem_readb(void *p_addr) {
- // p_addr: physical memory address which is to be accessed.
- // At boot time, kernel appears at linear base address
- // 0xC0000000, the space from 0x00000000 to 0xBFFFFFFF
- // is not mapped to any physical memory region. Thus,
- // Quafios kernel can not access anything in memory
- // except itself. Unfortunately, many data structures,
- // like the multiboot info structure (mbi), reside outside
- // the kernel... somewhere in physical memory referred
- // to by physical address pointers. Our mission is to re-map
- // physical_page so that it refers to the physical page
- // where p_addr refers.
- // p_addr = p_page (page base) + p_off (offset to that base).
- unsigned int p_page = ((unsigned int) p_addr) & PAGE_BASE_MASK;
- unsigned int p_off = ((unsigned int) p_addr) & (PAGE_SIZE-1);
- if (p_page != cur_physical_page)
- kmap((unsigned int) physical_page, cur_physical_page=p_page);
- return physical_page[p_off];
- }
- unsigned short pmem_readw(void *p_addr) {
- return (pmem_readb(p_addr+0)<< 0)
- + (pmem_readb(p_addr+1)<< 8);
- }
- unsigned int pmem_readl(void *p_addr) {
- return (pmem_readb(p_addr+0)<< 0)
- + (pmem_readb(p_addr+1)<< 8)
- + (pmem_readb(p_addr+2)<<16)
- + (pmem_readb(p_addr+3)<<24);
- }
- void *ppalloc() {
- unsigned int eflags = get_eflags();
- cli();
- if (!pfreelist.count) {
- set_eflags(eflags);
- return (void *) NULLPTR;
- }
- linknode *entry = pfreelist.first;
- linkedlist_remove(&pfreelist, pfreelist.first, NULLNODE);
- set_eflags(eflags);
- return (void *)((((unsigned int) entry) - ((unsigned int) &pmmap))*1024);
- }
- void ppfree(void *base) {
- unsigned int eflags = get_eflags();
- cli();
- linknode *entry = (linknode *) ((unsigned int) &pmmap[((unsigned int)base)/PAGE_SIZE]);
- linkedlist_add(&pfreelist, entry);
- set_eflags(eflags);
- return;
- }
- void pmem_init() {
- // The multi-boot compliant boot loader which loads Quafios
- // should provide Quafios kernel with a valid "memory map".
- // In PC, for example, the boot loader shall read the memory
- // map from BIOS then pass it to the kernel during boot process.
- // The code below process this memory map and initializes
- // the "pfreelist" linkedlist according to that map.
- // Make sure the boot info struct is supplied with memory map:
- if (!(pmem_readl(&(mbi->flags)) & MULTIBOOT_INFO_MEM_MAP))
- idle();
- // Initialize pfreelist:
- linkedlist_init(&pfreelist);
- // Traverse over the memory map, and set RAM Regions as free:
- unsigned int mmap_start = pmem_readl(&(mbi->mmap_addr));
- unsigned int mmap_length = pmem_readl(&(mbi->mmap_length));
- unsigned int i = mmap_start;
- while (i < mmap_start + mmap_length) {
- // Scan a memory map entry.
- multiboot_memory_map_t *mbmm = (multiboot_memory_map_t *) i;
- unsigned int size = pmem_readl(&(mbmm->size));
- unsigned int addr = pmem_readl(&(mbmm->addr));
- unsigned int len = pmem_readl(&(mbmm->len ));
- unsigned int type = pmem_readl(&(mbmm->type));
- // update the pointer.
- i += size + sizeof(mbmm->size);
- // skip if the region is not RAM:
- if (type != MULTIBOOT_MEMORY_AVAILABLE) continue;
- // update ram size:
- ram_size = addr + len;
- // Align to 4KB Boundary:
- if (addr & (PAGE_SIZE-1)) {
- len -= PAGE_SIZE-(addr&(PAGE_SIZE-1));
- addr = (addr & PAGE_BASE_MASK) + PAGE_SIZE;
- }
- unsigned int j = 0;
- while(j < len/PAGE_SIZE) {
- unsigned int frame = (addr/PAGE_SIZE) + j++;
- unsigned int page = frame * PAGE_SIZE;
- if (page < KERNEL_PHYSICAL_START ||
- page > KERNEL_PHYSICAL_END)
- // add the page to free list as long
- // as it is not a kernel page:
- linkedlist_addlast(&pfreelist,
- (linknode *) &pmmap[frame]);
- pmem_usable_pages++;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement