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.
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 , applications won't write to it without an exception ).
#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
}
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.
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 wrote:(Yes, I'm going with the W98\WME structure, but I'm going to do it properly this time , 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])
#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".
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.
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!
#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
}