Page 1 of 1

I just can't get the paging to work

Posted: Wed Jan 18, 2006 12:17 pm
by seph
Please read my last post in this thread.

Code: Select all

void paging_install()
{
   unsigned long *page_dir = (unsigned long *) 0x9C000;
   unsigned long *page_table = (unsigned long *) 0x9D000;
   
   unsigned long address = 0;
   unsigned int i;

   for (i=0; i<1024; i++)
   {
      page_table[i] = address | 3;
      address = address + 4096;
   }

   page_dir[0] = ((unsigned long) page_table) | 3;

   for (i= 1; i<1024; i++)
   {
      page_dir[i] = 0 | 2;
   }

   unsigned long *page_table2 = (unsigned long *) 0x9E000;
   address = 0xB8000;
   for (i=0; i<1024; i++)
   {
      page_table2[i] = address | 3;
      address = address + 4096;
   }
   page_dir[896] = ((unsigned long) page_table2) | 3;

   write_cr3(page_dir);
   write_cr0( read_cr0() | 0x80000000);
}
Most of that is right from a tutorial on paging, but I added some lines to page 0xB8000 - video memory to 0xE0000000.
In short, I put a page table for that at 0x9E000, mark all entries in it with the right address and as present read/write.
Then I enter that table into the page directory at entry 896 which is 1110000000 in binary (first 10 bits of E0000000).

After looking through every tutorial and guide to paging I could find, I finally gave up. I can see no problems in that code. Still outputing text to 0xE0000000 doesn't work while outputing to 0xB8000 does.

Edit.
Cleaned up the code a bit.

Re:I just can't get the paging to work

Posted: Wed Jan 18, 2006 1:24 pm
by Kevin McGuire
physical virtual length
0x0 0x0 0x400000
0xB8000 0xDFC00000 0x400000

That is your virtual memory map.

You did.
896 * 0x1000 * 0x400 = 0xE0000000
896 * 4096 * 1024 = 0xE0000000

You math has to compensate for the directory entries starting at array entry[zero].

(896 - 1) * 0x1000 * 0x400 = 0xDFC00000

You were right. You place the table at the 896 entry in the page directory.. but.. you placed it at the 897'th entry.

Try:
page_dir[895] = ((unsigned long) page_table2) | 3;

[edit]
I think im wrong. wrong. wrong. wrong. I am going to leave this here - so I can come back and read about how dumb I am. :)

Re:I just can't get the paging to work

Posted: Wed Jan 18, 2006 1:25 pm
by kataklinger
Have you tried to set that memory (0xE0000000) as uncachable? When you use standard address for VGA that region is marked as unchachable in MTTRs.

Re:I just can't get the paging to work

Posted: Wed Jan 18, 2006 5:36 pm
by seph
kmcguire: That obviously didn't work, but thanks anyway.

kataklinger: How do you do that?

Re:I just can't get the paging to work

Posted: Wed Jan 18, 2006 5:47 pm
by kataklinger
Set WT bit in PTE, you can set CD bit too but it is not nessery. When you do that CPU will write data to to chache but also it will send data to front side bus, this is only true for pages which ar marked as WT (write-throught).

Re:I just can't get the paging to work

Posted: Sun Jan 22, 2006 4:47 pm
by seph
I'm sorry, but it still doesn't seem to work.

I think I'll try converting everything to asm and see if that makes any difference...

Re:I just can't get the paging to work

Posted: Mon Jan 23, 2006 5:38 pm
by seph
I hate to double-post but...

Code: Select all

#include <includes.h>

void paging_install()
{
   unsigned long *page_dir = (unsigned long *) 0x90000;
   unsigned long *page_tablea = (unsigned long *) 0x9E000;
   unsigned long *page_tableb = (unsigned long *) 0x9D000;
   
   unsigned long address = 0;
   unsigned int i;

   for (i= 0; i<1024; i++)
   {
      page_dir[i] = 0 | 2;
   }

   for (i=0; i<1024; i++)
   {
      page_tablea[i] = address | 3;
      address = address + 4096;
   }
   page_tablea[185] = 0xB8000|3;
   page_dir[0] = ((unsigned long) page_tablea) | 3;

   page_tableb[0] = 0xB8000|3;
   page_dir[63] = ((unsigned long) page_tableb) | 3;

   write_cr3(page_dir);
   write_cr0( read_cr0() | 0x80000000);
}
Now, this code works, and maps the video memory to 0xFC00000 whitout problem.
But... as soon as I change page_dir[63] to page_dir[64] or anything above, I get a General Protection Fault. The position of the page directory doesn't seem to matter.

It seems I can only use 256 mb of virtual memory (?).
For clarity:
I am loading this using GRUB with this multiboot-header:

Code: Select all

MULTIBOOT_PAGE_ALIGN   equ 1<<0
   MULTIBOOT_MEMORY_INFO   equ 1<<1
   MULTIBOOT_AOUT_KLUDGE   equ 1<<16
   MULTIBOOT_HEADER_MAGIC   equ 0x1BADB002
   MULTIBOOT_HEADER_FLAGS   equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
   MULTIBOOT_CHECKSUM   equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
   EXTERN code, bss, end

   dd MULTIBOOT_HEADER_MAGIC
   dd MULTIBOOT_HEADER_FLAGS
   dd MULTIBOOT_CHECKSUM

   dd mboot
   dd code
   dd bss
   dd end
   dd start
Could it be loading in some kind of weird 1/16 memory protected mode?

Re:I just can't get the paging to work

Posted: Mon Jan 23, 2006 6:39 pm
by Brendan
Hi,
seph wrote:But... as soon as I change page_dir[63] to page_dir[64] or anything above, I get a General Protection Fault. The position of the page directory doesn't seem to matter.
If it was a paging problem you'd get a page fault.

What are your segment limits? It's possible that your GDT isn't quite right....


Cheers,

Brendan

Re:I just can't get the paging to work

Posted: Tue Jan 24, 2006 11:15 am
by seph
The segment limits are 0xFFFFFFFF

Re:I just can't get the paging to work

Posted: Tue Jan 24, 2006 11:49 am
by Brendan
Hi,
seph wrote:The segment limits are 0xFFFFFFFF
Are you sure the segment limits aren't 0xFFFFFFF instead?

If this isn't the cause of your general protection fault, then more information would help - what does the CPU push on the stack when the GPF is generated (CS:EIP and error code) and what code is the CPU trying to run at the time...


Cheers,

Brendan

Re:I just can't get the paging to work

Posted: Tue Jan 24, 2006 1:38 pm
by seph
I'm sorry.
My isrs-routines weren't working correctly...
:-[
It was in fact a page fault.
What does that mean then?
That I have to move my page tables to somewhere else?

I'll return later with more info on this...

Edit:
Ok... I got it now.
The problem was in my routines for setting GDT gates.
...I had mixed 0xF0 with 0x0F...
Everything works now!

Thanks a lot to everyone for their help and remarkably quick replies!