Physical mem alloc

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Beastie
Posts: 14
Joined: Sun Jan 21, 2007 6:31 pm

Physical mem alloc

Post by Beastie »

hi,

I'm currently using a bitmap for my physical mem. allocation, I've a question regarding this.

Where should i put the bitmap, should i use a predefined region as 0x600000 or should i allocate it in the BSS, or should i dynamically search the mem. map and find out how much mem. I've then alloc. the space for the bitmap by hand and mark it as allocated later.
I know that Linux uses a buddy system but where it saves the allocator data ?????
User avatar
Jef
Member
Member
Posts: 112
Joined: Tue Jan 08, 2008 7:25 am
Location: Greece
Contact:

Re: Physical mem alloc

Post by Jef »

Beastie wrote:Where should i put the bitmap, should i use a predefined region as 0x600000 or should i allocate it in the BSS, or should i dynamically search the mem. map and find out how much mem. I've then alloc. the space for the bitmap by hand and mark it as allocated later.
At my OS i have put the memory manager map at 400000h.
While the initialization of memory manager (that must be at the very start of OS load, e.g. Just after entering PMode) i cleanup the memory map area (size 0FFFFFh) and then i set that this area is used.
After that the "my_malloc" can be called to allocate memory.

Just keep in mind that some other areas are already used (BIOS, VGA RAM, etc), so remember to "set" as allocated before memory manager init ends.
Keep coding...
...the sky is the limit

AsteriOS project: http://www.mindfields.gr/main/index.php ... &Itemid=27
User avatar
Assembler
Member
Member
Posts: 30
Joined: Fri Oct 27, 2006 5:26 am
Contact:

Post by Assembler »

Hello,

Once before I had a conversation with Kirk McKusick regarding the design of a physical memory manager. Here is what he says:
I would recommend doing something similar to what the FreeBSD does.
At boot time you know the amount of physical memory available on the
machine. Deduct the amount dedicated to the kernel and allocate space
in the kernel's address space to describe the remaining memory.
FreeBSD allocates a vmpage structure to describe each page and a
base-and-bound bitmap to describe their allocation (which allows for
quick allocation lookup for first-best-fit). If you wish to pursue
this approach, I highly recommend that you read chapter 5 of my
textbook ``The Design and Implementation of the FreeBSD Operating
System.''

Kirk McKusick
Thanks.
Systems and Computer Engineering Researcher
"Do you pine for the nice days of Minix-1.1, when men were men and wrote their own device drivers?" -- Linus Torvalds
http://sce.carleton.ca/~maslan
essial
Member
Member
Posts: 26
Joined: Sat Mar 01, 2008 10:23 pm

Post by essial »

I use GRUB to load my kernel, compile an gzip'd elf kernel, and have the linker set to load the kernel at 0x100000 (1meg). The kernel runs managed applications, so the kernel is mapped to all of ram. Here is my linker script:

Code: Select all

OUTPUT_FORMAT("elf32-i386")
ENTRY(_start)
phys = 0x00100000; /* 1 meg */
SECTIONS
{   .text phys : AT(phys)
    {   code = .;
        *(.text)
        . = ALIGN(4096); 
    }
    .data :  AT(phys + (data - code))
    {   data = .;
         *(.data)
         . = ALIGN(4096); 
    }
    .bss :  AT(phys + (bss - code))
    {   bss = .;
        *(.bss)
        *(COMMON)
        . = ALIGN(4096); 
    }
    end = .; _end = .; __end = .;
}
When my memory manager starts up, I loop through the memory map grub provides me (which is most likely the same thing that you have). I have a fixed length table (16k worth) of information about what memory is mapped where. Each user-usable block of memory I encounter, I add an entry to that table. During the course of adding the record, I check the base address and length to determine if the kernel is located inside of that memory block. If it is, I do simple math to adjust the map to either end before, or start after the block (or disregard the block if it happens to be the exact same size). I do that by using the "end" and "phys" variables from my linker script:

Code: Select all

extern void* end;
extern void* phys;
...

// Adjust the memory block if it begins inside of the kernel block
if ( (MemBlock[i].Base >= (unsigned long)&phys) && (MemBlock[i].Base <= (unsigned long)&end) )
{
	// This block starts inside of kernel memory, so first get the amount we must remove
	unsigned long rAmt = MemBlock[i].Base - (unsigned long)&phys;
	
	// Add the removed amount to the base, and subtract it from the length
	MemBlock[i].Base += rAmt;
	MemBlock[i].Length -= rAmt;
}

// Adjust the memory block if it ends inside of the kernel block			
if ( ((MemBlock[i].Base+MemBlock[i].Length) >= (unsigned long)&phys) && ((MemBlock[i].Base+MemBlock[i].Length) <= (unsigned long)&end) )
{
	// This block ends inside of kernel memory, so first get the amount we must truncate
	unsigned long rAmt = (MemBlock[i].Base+MemBlock[i].Length)- (unsigned long)&end;
	
	// Now we simply subtract it from the length of the map
	MemBlock[i].Length -= rAmt;
}
After that point, I can use whatever memory I have in my table.

As far as your memory map table, you can either go my route, and use a constant array, or you can just have an array of maby 15 elements (just to be safe) to store the initial user memory, minus where the kernel is.
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

Physical memory manager... well, for memory that doesn't have to be contiguous (pretty much anyhing over 16mb if you plan on supporting ISA devices, if no ISA support is required or desired, you can just use things above 1mb or so). Anyways... in mine, I barely use any memory at all for storing the pages. I use a linked list type structure like so:

Each physical page has an entry pointing to the next physical page. I save the first page in the list in a variable. So, on allocation, I grab the page pointed to in the variable, read it's first 4-bytes (pointer to the next free page) and store it to my "first page" variable and hand the page off to whatever asked for it. On de-allocation, I simply write the first 4-bytes with the first page variable, and point the first page variable to the just reelased page. The benefit is, when all memory is allocated, I am using almost zero memory, even if nothing is allocated, I don't have to set any additional memory aside. I simply initialize it on boot-up, and let it run from then on out :). Now, for memory under 1mb I reserve for use with legacy devices and such, other than that. After receiving the memory table from the bios, I just loop through and mark each page as required.
Post Reply