Page 1 of 1

Multiboot Paging Woes

Posted: Sun Mar 05, 2006 10:27 am
by elaverick
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.

My paging setup looks like this -

Code: Select all

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

};
My bootloader is as follows:

Code: Select all

global _loader           ; making entry point visible to linker
extern _k_main           ; _main is defined elsewhere

; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ  1<<0                   ; align loaded modules on page boundaries
MEMINFO     equ  1<<1                   ; provide memory map
FLAGS       equ  MODULEALIGN | MEMINFO  ; this is the Multiboot 'flag' field
MAGIC       equ    0x1BADB002           ; 'magic number' lets bootloader find the header
CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum required

section .text
align 4
MultiBootHeader:
   dd MAGIC
   dd FLAGS
   dd CHECKSUM

; reserve initial kernel stack space
STACKSIZE equ 0x4000          ; that's 16k.

_loader:
   mov esp, stack+STACKSIZE           ; set up the stack
   push eax                           ; pass Multiboot magic number
   push ebx                           ; pass Multiboot info structure

   call _k_main                        ; call kernel proper
               hlt                    ; halt machine should kernel return

section .bss
align 32
stack:
   resb STACKSIZE      ; reserve 16k stack on a quadword boundary
What have I done wrong or am I just missing something fundamental about the entire experience :)

Thanks
E

Re:Multiboot Paging Woes

Posted: Sun Mar 05, 2006 12:14 pm
by McZ
elaverick wrote: My paging setup looks like this -

Code: Select all

   // 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.

Re:Multiboot Paging Woes

Posted: Sun Mar 05, 2006 12:32 pm
by elaverick
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.

Re:Multiboot Paging Woes

Posted: Mon Mar 06, 2006 3:51 am
by xenos
elaverick wrote:

Code: Select all

???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).

Re:Multiboot Paging Woes

Posted: Mon Mar 06, 2006 6:52 am
by elaverick
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.

Thanks for your help so far tho :)