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.
Ok, I've recently moved my Kernel over so that it boots in Multiboot mode via GRUB cheifly because I was looking for a way of making paging easier. That all seems to have worked fine and my (very)basic Kernel loads and outputs to the screen without complaint. However as soon as I try and Initialize basic paging I get a crash from BOCHS complaining that I am running in Bogus Memory. I assume this means I'm misaddressing something.
void Init_Paging()
{
unsigned long address=0; // holds the physical address of where a page is
unsigned int i;
// map the first 4MB of memory
for(i=0; i<1024; i++)
{
g_page_table[i] = address | 0x3; // attribute set to: supervisor level, read/write, present(011 in binary)
address = address + 4096; // 4096 = 4kb
};
// fill the first entry of the page directory
g_page_directory[0x0] = ((int)g_page_table + 0x40100000) | read_write | present;
g_page_directory[0x300] = ((int)g_page_table + 0x40100000) | read_write | present;
// set the rest of the pages to empty
for(i=1; i<1024; i++)
{
g_page_directory[i] = 0|read_write; // attribute set to: supervisor level, read/write, not present(010 in binary)
};
// write_cr3, read_cr3, write_cr0, and read_cr0 all come from the assembly functions
write_cr3((int)g_page_directory + 0x40100000); // put that page directory address into CR3
write_cr0(read_cr0() | 0x80000000); // set the paging bit in CR0 to 1
};
// fill the first entry of the page directory
g_page_directory[0x0] = ((int)g_page_table + 0x40100000) | read_write | present;
g_page_directory[0x300] = ((int)g_page_table + 0x40100000) | read_write | present;
// set the rest of the pages to empty
for(i=1; i<1024; i++)
{
g_page_directory[i] = 0|read_write; // attribute set to: supervisor level, read/write, not present(010 in binary)
};
isn't it a bad idea to clear the page directory AFTER you have set your entries? I can see that you start with i=1 this doesn't clear the first entry though but entry 0x300 will be cleared.
EDIT: I assume you want to map your kernel at 3gb (0x300 entry) and iirc you need a jump after paging is enabled else you will still be running in low memory.
Ah thats set for HigherHalf mapping isn't it... yes good point.
I can't get the Higher Half barebones to compile properly as it returns 3rd (13) exception that I just can't track down.
I'll swap those loops around and have another go with the higher half stuff. Any other suggestion to get this working (either Higher Half or Lower at the moment) would be greatly appriciated.
???g_page_directory[0x0] = ((int)g_page_table + 0x40100000) | read_write | present;
g_page_directory[0x300] = ((int)g_page_table + 0x40100000) | read_write | present;
???write_cr3((int)g_page_directory + 0x40100000); // put that page directory address into CR3
What is the "+ 0x40100000" good for? As far as I can see, you start without paging enabled, so g_page_table and g_page_directory contain the physical address of your page table and directory. Since you need to enter these physical addresses into the page directory and CR3, there shouldn't be any offset.
If your kernel is linked to some higher memory area, it is running "at the wrong place" before paging is enabled and you have to correct all addresses with some constant offest. So in that case you should also fill the tables at address (g_page_table + offset) and (g_page_directory + offset).
Ugh you're right, I'm not entirely sure where that code came from, I think I must have been dodging between different tutorials in order to get something working. I think I now how basic paging enabled (it compiles and runs anyway).
I'm now just trying to figure out how the bitmap relates to the page directory... if the bitmap just shows whether the page is available or not why can't you just step through the directory and do the same thing there? I'm still missing something fundamental here aren't I.