Physical MM

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
Cjmovie

Physical MM

Post by Cjmovie »

I wrote a MM from scratch, I think it's fine, but I'd like to know other peoples opinions. Also note that it is hardcoded not to mess with the first MB of memory. That way I don't have to protect bios ROM etc.

While I'm at it, what do you think of my idea that after my kernel enables paging, it turns itself off and loads a second-level kernel. Which really makes the first kernel a really advanced bootloader. That way I can load my 'real' kernel in the top 2GB of address space (Yes, I'm going with the W98\WME structure, but I'm going to do it properly this time :P, applications won't write to it without an exception :) ).

Here's it:

Code: Select all

#include <stdio.h>

unsigned int *MemoryTablePtr = NULL; //Ptr to bitmap of used memory
unsigned int HalfMBAvailable = 0;    //Memory in system, in half MB's

void SetMemoryTable(UINT NewPtr){    //Set bitmap location for memory
 UINT i;                             //Counter variable
 MemoryTablePtr = NewPtr;            //Set our pointer to that
 for(i=0; i<32768; i++)MemoryTablePtr[i] = 0;  //All not in use
 for(i=0; i<8; i++)MemoryTablePtr[i] = 2^32-1; //1st MB never used!
}

void SetSystemRAM(UINT num){         //Set system RAM in MB's
 HalfMBAvailable = num*2;            //Set it in our sub-system
}

void* PageAlloc(){                   //Allocate one 4kb page, return ptr
 UINT i, c;                          //Counter/Loop variables
 
 if(MemoryTablePtr == NULL)return NULL; //No Bitmap? Can't continue, abort
 
 for(i=0; i<HalfMBAvailable; i++)    //Loop through all 32-part bit entries
  if(MemoryTablePtr[i] != 2^32-1){   //Is there a SINGLE free page?
   for(c=0; c<32; c++){              //Yes, find which one
    if(MemoryTablePtr[i] & 2^c == 0){//Is it this one/is this bit unset?
     MemoryTablePtr[i] |= 2^c;       //Yes, now set it as used!
     return (void*)((i*32+c) * 4096); //Return pointer to page!
    }
   }
  }
 
 return NULL;                        //No free pages? Sorry, NULL!
}

void PageFree(void* ptr){            //Tell us a page's use is done!
 UINT index, bit;                    //Dword inex and bit
 ptr = ptr & ~(4095);                //Align to page-boundary, in case!
 ptr /= 4096;                        //Get Page index
 bit = ptr%32                        //Get bit in dword in index
 rem = ptr/32;                       //Get DWORD to lookup
 MemoryTablePtr[ptr/32] &= ~(2^bit); //Set it as free
}
Visitor..

Re:Physical MM

Post by Visitor.. »

There's one obvious problem: your use of the ^ -operator, which isn't the exponent operator but XOR. Luckily, when using 2 as the base there's an easy way to fix that: operator << (left shift). Just change any occurences of 2^x in your code to 1<<x.
Visitor..

Re:Physical MM

Post by Visitor.. »

When you have done the conversion your compiler may or may not like the 1<<32-1 -constant because it overflows. Instead, you should use, for example, 0xffffffff.
Cjmovie

Re:Physical MM

Post by Cjmovie »

Thanks "Visitor..."

I fixed that, now to test....
AR

Re:Physical MM

Post by AR »

Cjmovie wrote:(Yes, I'm going with the W98\WME structure, but I'm going to do it properly this time :P, applications won't write to it without an exception :) ).
Windows doesn't actually use 2GB for the kernel, it's memory layout is like this:
  • 4MB-2GB = Program (code,data,bss,heap,empty space, stack)
  • 2-3GB = "System memory" (this is where DLLs go, DLLs are part of the program, not the kernel though, this space is switched with the rest of the process - there is also apparently a global heap in here somewhere along with a 'system call method' page)
  • 3-4GB = Kernel, drivers, ring 0 services ("services" is mainly just the virtual memory manager and device manager which are supposedly seperate programs from the kernel [in NT that is])
Cjmovie

Re:Physical MM

Post by Cjmovie »

I meant having Program-Stack-Kernel, not exact numbers.

I have no DLL's......
Cjmovie

Re:Physical MM

Post by Cjmovie »

Code: Select all

#include <stdio.h>

//NOTE! This memory manager requires at least 128KB of contigous space!
void* MemoryTablePages;

unsigned int *MemoryTablePtr = NULL; //Ptr to bitmap of used memory
unsigned int HalfMBAvailable = 0;    //Memory in system, in half MB's

void SetMemoryTable(UINT NewPtr){   //Set bitmap location for memory
 UINT i;                            //Counter variable
 NewPtr = NewPtr & ~(0x1FFFF);      //MUST align to 128k boundary
 MemoryTablePtr = (UINT*)NewPtr;    //Set our pointer to that
 MemoryTablePages = (UINT*)(NewPtr/32);//Index to bitmap for pages used by bitmap
 for(i=0; i<32768; i++)MemoryTablePtr[i] = 0;  //All not in use
 for(i=0; i<8; i++)MemoryTablePtr[i] = 0xFFFFFFFF; //1st MB never used!
 //Never give out memory bitmap pages!
 MemoryTablePtr[(UINT)MemoryTablePages] = 0xFFFFFFFF;
}

void SetSystemRAM(UINT num){          //Set system RAM in MB's
 HalfMBAvailable = num*2;             //Set it in our sub-system
}

void* PageAlloc(){                    //Allocate one 4kb page, return ptr
 UINT i, c;                           //Counter/Loop variables
 
 if(MemoryTablePtr == NULL)return NULL; //No Bitmap? Can't continue, abort
 
 for(i=8; i<HalfMBAvailable; i++)     //Loop through all 32-part bit entries
  if(MemoryTablePtr[i] != 0xFFFFFFFF){//Is there a SINGLE free page?
   Print("\n[MEM ] Found open dword\n");
   for(c=0; c<32; c++){               //Yes, find which one
    if(MemoryTablePtr[i] & (1<<c) == 0){//Is it this one/is this bit unset?
     MemoryTablePtr[i] |= 1<<c;       //Yes, now set it as used!
     Print("[MEM ] Gave out one chunk\n");
     return (void*)((i*32+c) * 4096); //Return pointer to page!
    }
   }
  }
 
 Print("\n[MEM ] Out of memory\n");
 return NULL;                        //No free pages? Sorry, NULL!
}

void PageFree(void* optr){           //Tell us a page's use is done!
 UINT index, bit, ptr;               //Dword index and bit. tmp for math op
 ptr = (UINT)optr;                 //So no errors on compile, use UINT not void*
 ptr = ptr & 0xFFFFF000;             //Align to page-boundary, in case!
 ptr = ptr/4096;                     //Get Page index
 bit = ptr%32;                       //Get bit in dword in index
 index = ptr/32;                     //Get DWORD to lookup
 MemoryTablePtr[index] &= ~(1<<bit); //Set it as free
}
For some reason it always reports "out of memory" when I call PageAlloc and returns a NULL. Although it does find space in every dword and says "Found Open Dword".
FlashBurn

Re:Physical MM

Post by FlashBurn »

If you want you can have a look at my pmm (bitmap based). It is the C code which I ported from my asm code. It should work, but I haven?t tested it so much.
Cjmovie

Re:Physical MM

Post by Cjmovie »

Well your code didn't REALLY help, but.......
I decided I liked your idea to use #define macro's and I switched it all to use my version of them. Turns out that fixed it and it works perfect now....Thanks!

For the record:

Code: Select all

#include <stdio.h>

//NOTE! This memory manager requires at least 128KB of contigous space!
void* MemoryTablePages;

unsigned int *MemoryTablePtr = NULL; //Ptr to bitmap of used memory
unsigned int HalfMBAvailable = 0;    //Memory in system, in half MB's

#define SetBitMacro(x,bit) x |= (1 << bit)
#define DelBitMacro(x,bit) x &= ~(1 << bit)
#define GetBitMacro(x,bit) (x & (1 << bit))

void SetMemoryTable(UINT NewPtr){   //Set bitmap location for memory
 UINT i;                            //Counter variable
 NewPtr = NewPtr & ~(0x1FFFF);      //MUST align to 128k boundary
 MemoryTablePtr = (UINT*)NewPtr;    //Set our pointer to that
 MemoryTablePages = (UINT*)(NewPtr/32);//Index to bitmap for pages used by bitmap
 for(i=0; i<32768; i++)MemoryTablePtr[i] = 0;  //All not in use
 for(i=0; i<8; i++)MemoryTablePtr[i] = 0xFFFFFFFF; //1st MB never used!
 //Never give out memory bitmap pages!
 MemoryTablePtr[(UINT)MemoryTablePages] = 0xFFFFFFFF;
}

void SetSystemRAM(UINT num){          //Set system RAM in MB's
 HalfMBAvailable = num*2;             //Set it in our sub-system
}

void* PageAlloc(){                    //Allocate one 4kb page, return ptr
 UINT i, c;                           //Counter/Loop variables
 
 if(MemoryTablePtr == NULL)return NULL; //No Bitmap? Can't continue, abort
 
 for(i=8; i<HalfMBAvailable; i++)     //Loop through all 32-part bit entries
  if(MemoryTablePtr[i] != 0xFFFFFFFF){//Is there a SINGLE free page?
   Print("\n[MEM ] Found open dword\n");
   for(c=0; c<32; c++){               //Yes, find which one
    if(!GetBitMacro(MemoryTablePtr[i], c)){//Is it this one/is this bit unset?
     SetBitMacro(MemoryTablePtr[i], c); //Yes, now set it as used!
     Print("[MEM ] Gave out one chunk\n");
     return (void*)((i*32+c) * 4096); //Return pointer to page!
    }
   }
  }
 
 Print("\n[MEM ] Out of memory\n");
 return NULL;                        //No free pages? Sorry, NULL!
}

void PageFree(void* optr){           //Tell us a page's use is done!
 UINT index, bit, ptr;               //Dword index and bit. tmp for math op
 ptr = (UINT)optr;                 //So no errors on compile, use UINT not void*
 ptr = ptr & 0xFFFFF000;             //Align to page-boundary, in case!
 ptr = ptr/4096;                     //Get Page index
 bit = ptr%32;                       //Get bit in dword in index
 index = ptr/32;                     //Get DWORD to lookup
 DelBitMacro(MemoryTablePtr[index], bit); //Set it as free
}
BTW, I just permanently switched to firefox
Post Reply