// mm.c // Author: Josh Holtrop // Created: 09/01/03 // Modified: 03/08/04 #include "hos_defines.h" #include "mm.h" //The total amount of physical memory available (bytes, 1 bit per page) #define BITMAP_SIZE 0x20000 dword mm_totalmem = 0; dword mm_megabytes = 0; byte page_bitmap[BITMAP_SIZE]; //used to store a bit for each page that is used, 0 if available //0x20000*(8 bits/byte)=0x100000 pages in 4gb total //This function initializes the memory manager's linked list, filling it with the // memory areas returned by bios interrupt 0x8E20 void mm_init() { dword memmap_entries = *(dword *)BOOT_MEMMAP_ENTRIES; memmap_entry *maps = (memmap_entry *) BOOT_FIRST_MEMMAP; dword a; for (a = 0; a < BITMAP_SIZE; a++) { page_bitmap[a] = 0xFF; //all pages used } for (a = 0; a < memmap_entries; a++) { if (maps[a].attributes == 1) // (1) mem free to OS { mm_totalmem += maps[a].limit.lowdword; if ((maps[a].base.lowdword + maps[a].limit.lowdword) >= (FREERAM_START+4096)) //goes past where we start freeram { if (maps[a].base.lowdword < FREERAM_START) { mm_pfreen(FREERAM_START, (maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword)) >> 12); } else { mm_pfreen(maps[a].base.lowdword, maps[a].limit.lowdword >> 12); //set the appropriate bits as "free" in the page bitmap } } } } if (mm_totalmem % 0x100000) mm_megabytes = (mm_totalmem >> 20) + 1; else mm_megabytes = mm_totalmem >> 20; } // This function frees a certain number of pages starting at the address // specified in base for a length of pages pages void mm_pfreen(dword base, dword pages) { dword a; dword max = base + (pages << 12); for (a = base; a < max; a += 4096) { mm_pfree(a); } } // This function frees a single page void mm_pfree(dword base) { // dword pageNumber = base >> 12; // >>12 == /4096 dword byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8 dword bitNumber = (base >> 12) % 8; //pageNumber % 8; page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF); } // This function allocates a single page, returning its physical address void *mm_palloc() { dword bite; for (bite = 0; bite < BITMAP_SIZE; bite++) { if (page_bitmap[bite] != 0xFF) //there is an available page within this 8-page region { int bit; for (bit = 0; bit < 8; bit++) { if (!(page_bitmap[bite] & (1 << bit))) //this bite/bit combination is available { page_bitmap[bite] = page_bitmap[bite] | (1 << bit); //set page as used return (void *)((bite << 15) | (bit << 12)); } } } } return 0; //no free page } // This function reports the number of bytes of free physical memory dword mm_freemem() { dword a; dword pages = 0; for (a = 0; a < BITMAP_SIZE; a++) { int bit; for (bit = 0; bit < 8; bit++) { if (!(page_bitmap[a] & (1 << bit))) pages++; } } return pages << 12; } dword mm_getTotalMem() { return mm_totalmem; } dword mm_getTotalMegs() { return mm_megabytes; }