156 lines
3.8 KiB
C
156 lines
3.8 KiB
C
// mm.c
|
|
// Author: Josh Holtrop
|
|
// Created: 09/01/03
|
|
// Modified: 07/12/04
|
|
|
|
#include "kernel.h"
|
|
#include "mm/mm.h"
|
|
#include "multiboot.h"
|
|
#include "hos_defines.h"
|
|
|
|
extern mb_info_t mb_info_block;
|
|
extern mb_mmap_t mb_mmap[MAX_MMAP];
|
|
extern u32_t mmap_entries;
|
|
extern mb_module_t mb_modules[MAX_MODULES];
|
|
|
|
u32_t mm_totalmem;
|
|
u32_t mm_megabytes;
|
|
u32_t mm_freepages;
|
|
u32_t mm_first_free_byte;
|
|
byte page_bitmap[MM_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()
|
|
{
|
|
u32_t a;
|
|
for (a = 0; a < MM_BITMAP_SIZE; a++) //mark all pages used
|
|
{
|
|
page_bitmap[a] = 0xFF;
|
|
}
|
|
for (a = 0; a < mmap_entries; a++) //free BIOS #1 areas
|
|
{
|
|
if (mb_mmap[a].type == 1) // (1) mem free to OS
|
|
{
|
|
mm_totalmem += mb_mmap[a].length;
|
|
u32_t freethis = mb_mmap[a].base;
|
|
u32_t limit = mb_mmap[a].base + mb_mmap[a].length - 4096;
|
|
while (freethis <= limit)
|
|
{
|
|
if (freethis >= PHYS_LOAD) //above physical kernel load point
|
|
mm_pfree(freethis);
|
|
freethis += 4096;
|
|
}
|
|
}
|
|
}
|
|
mm_preserven(PHYS_LOAD, (((u32_t)&_end - (u32_t)&start) >> 12) + 1); //reserve kernel memory
|
|
int i;
|
|
for (i = 0; i < mb_info_block.mods_count; i++) //reserve module memory
|
|
{
|
|
mm_preserven(mb_modules[i].mod_start - VIRT_OFFSET, (mb_modules[i].mod_end - mb_modules[i].mod_start) >> 12);
|
|
}
|
|
mm_megabytes = (mm_totalmem >> 20) + ((mm_totalmem % 0x100000) ? 1 : 0);
|
|
}
|
|
|
|
|
|
// This function frees a certain number of pages starting at the address
|
|
// specified in base for a length of pages pages
|
|
void mm_pfreen(u32_t base, u32_t pages)
|
|
{
|
|
//convert pages to max address
|
|
for (pages = base + (pages << 12); base < pages; base += 4096)
|
|
mm_pfree(base);
|
|
}
|
|
|
|
|
|
// This function frees a single page
|
|
void mm_pfree(u32_t base)
|
|
{
|
|
// u32_t pageNumber = base >> 12; // >>12 == /4096
|
|
u32_t byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
|
|
u32_t bitNumber = (base >> 12) & 0x07; //pageNumber % 8;
|
|
page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF);
|
|
mm_freepages++;
|
|
if (byteNumber < mm_first_free_byte)
|
|
mm_first_free_byte = byteNumber;
|
|
}
|
|
|
|
|
|
// This function reserves a certain number of pages starting at the address
|
|
// specified in base for a length of pages pages
|
|
void mm_preserven(u32_t base, u32_t pages)
|
|
{
|
|
//convert pages to max address
|
|
for (pages = base + (pages << 12); base < pages; base += 4096)
|
|
mm_preserve(base);
|
|
}
|
|
|
|
|
|
// This function reserves a single page
|
|
void mm_preserve(u32_t base)
|
|
{
|
|
// u32_t pageNumber = base >> 12; // >>12 == /4096
|
|
u32_t byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
|
|
u32_t bitNumber = (base >> 12) & 0x07; //pageNumber % 8;
|
|
page_bitmap[byteNumber] = page_bitmap[byteNumber] | (0x01 << bitNumber);
|
|
mm_freepages--;
|
|
}
|
|
|
|
|
|
// This function allocates a single page, returning its physical address
|
|
u32_t mm_palloc()
|
|
{
|
|
u32_t bite;
|
|
for (bite = mm_first_free_byte; bite < MM_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
|
|
{
|
|
mm_first_free_byte = bite; //start searching from here next time
|
|
mm_freepages--;
|
|
page_bitmap[bite] = page_bitmap[bite] | (1 << bit); //set page as used
|
|
return ((bite << 15) | (bit << 12));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0; //no free page
|
|
}
|
|
|
|
|
|
// This function reports the number of bytes of free physical memory
|
|
u32_t mm_getFreeMem()
|
|
{
|
|
return mm_freepages << 12;
|
|
}
|
|
|
|
|
|
u32_t mm_getFreePages()
|
|
{
|
|
return mm_freepages;
|
|
}
|
|
|
|
|
|
u32_t mm_getTotalMem()
|
|
{
|
|
return mm_totalmem;
|
|
}
|
|
|
|
|
|
u32_t mm_getTotalMegs()
|
|
{
|
|
return mm_megabytes;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|