Physical Memory Manager

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
tigerfish
Posts: 12
Joined: Wed Jan 17, 2007 7:26 am

Physical Memory Manager

Post by tigerfish »

[code]
unsigned long base;
unsigned char memmap[131071]; // 1 Entry => 1Page
extern unsigned char* end;
unsigned long topoffset;

unsigned char* KeAllocPhysPage() {
unsigned int i;
for(i=0;i<topoffset;i++) {
if(memmap[i] == 0) {
memmap[i] = 1;
return ((unsigned char*)base + i*4096); // base + i pages
}
}
return (unsigned char*)0;
}

void KeFreePhysPage(unsigned char* addr) {
if( ((unsigned long) addr - base) / 4096 >= topoffset)
return;
else
memmap[ ((unsigned long) addr-base) / 4096] = 0;
}

void KeInitPhysPageMM(unsigned long memsize) {
base = ((unsigned long)end / 4096 + 1) * 4096;
memset(memmap,0,131071);
topoffset = (memsize - base) / 4096;
} [/code
This Physical Memory Manager Look good?[/code]
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

Looks alright, however I would probably change it to a bit array, rather than a byte array to cut down on memory consumption 8:1. Something like this:

Code: Select all

unsigned char memmap[131072/8]; //512 mb?

//Check if a page is available or in use
char CheckBit(unsigned long Page)
{
 unsigned long offset, bit;
 unsigned char Byte;
 offset = Page/8;
 bit = Page&7;
 bit = (1<<bit); //Make this it's bit value! (0=1,1=2,2=4,4=16,etc)
 Byte = memmap[offset]; //Grab that byte
 if ((bit&Byte) == bit)
  return 1; //This page is allocated
 return 0; //This page is free
}

void ChangeBit(unsigned long Page, char Value) //Value must be 0/1!
{
 unsigned long offset, bit, mask;
 unsigned char Byte;
 offset = Page/8;
 bit = Page&7;
 mask = ~(1<<bit); //Everything BUT this bit!
 bit = (Value<<bit); //If value ==0, value<<anything = 0, otherwise it's the bit value!
 Byte = memmap[offset]; //Grab that byte
 Byte&=mask; //Remove this value
 Byte|=bit; //Lets add this back in if it is set
 memmap[offset] = Byte; //Update our array
}
So instead of setting a byte for each page, you would just set a bit of each byte (so, 8 pages for each byte rather than 1 page per byte). This means, you will only use 16k rather than 128k for your memory table, a pretty nice savings (so, only 4 pages of physical memory used to store 512mb). Hope this helps.
tigerfish
Posts: 12
Joined: Wed Jan 17, 2007 7:26 am

Post by tigerfish »

Thanks. Mind you, each entry stores the information of 4KB's worth of memory.

Code: Select all

extern unsigned char end;
#define VROFFSET(x) x & 0xFFF // Phys Mem Offset // Lower 12 Bits
#define PTOFFSET(x) (x & 0x003FF000) >> 12 // PT Offset  // Middle 10
#define PDOFFSET(x) (x & 0xFFC00000) >> 22 // PD Offset  // High 10

void KeMapAddress(unsigned long* phys, unsigned long* virt, unsigned long* pagedir, unsigned long flags) {
	if(pagedir[PDOFFSET(virt)] == 0) 
		pagedir[PDOFFSET(virt)] = (unsigned long)KeAllocPhysPage() | flags;
        *(((unsigned long*)pagedir[PDOFFSET(virt)]) +  PTOFFSET(virt)) = phys | flags;
}

unsigned long* KeGetPhysAddress(unsigned long *virt, unsigned long* pagedir) {
	if(pagedir[PDOFFSET(virt) == 0)
		return 0;
	else
		return *(((unsigned long*)pagedir[PDOFFSET(virt)]) + PTOFFSET(virt)) & ~0xFFF;
}
	


unsigned long* KeMakePageDirectory(unsigned long cpl)  {
	unsigned long* pagedir = KeAllocPhysPage();
	unsigned long i,j;

	unsigned long rflags = cpl == 3 ?  5 : 1;
	unsigned long rwflags = cpl == 3 ? 7 : 3;

	for(i=0;i < ((unsigned long)&end / 4096 + 1) * 4096; i+= 4096) {
		KeMapAddress(i,i,pagedir,rflags) ;
	}
}
	
unsigned long* KeAllocPage(unsigned long* pagedir) {
	if(pagedir == 0)
		pagedir = KeReadCR3();
	unsigned long* curr = 0xD0000000;
	
	while(KeGetPhysAddress(curr,pagedir) == 0 && curr < 0xE0000000)
		curr += 4096;
	if(curr == 0xE0000000)
		return 0;
	else {
		KeMapPage(KeAllocPhysPage(),curr,pagedir, KeGetEFlags() & 0x3000 == 1 ? 7 : 3);
		return curr;
	}
}
Not to bother anyone, but does this VM look good right now?
User avatar
fontknocker
Posts: 16
Joined: Mon Dec 11, 2006 1:49 am
Location: Canberra, Australia

Post by fontknocker »

Hi,

Code: Select all

   while(KeGetPhysAddress(curr,pagedir) == 0 && curr < 0xE0000000)
      curr += 4096;
If I might ask, why did you choose this method instead of storing the address of the top of the kernel heap?

Regards.
Post Reply