I just can't get the paging to work

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
seph

I just can't get the paging to work

Post 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.
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

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

Post 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. :)
User avatar
kataklinger
Member
Member
Posts: 381
Joined: Fri Nov 04, 2005 12:00 am
Location: Serbia

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

Post 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.
seph

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

Post by seph »

kmcguire: That obviously didn't work, but thanks anyway.

kataklinger: How do you do that?
User avatar
kataklinger
Member
Member
Posts: 381
Joined: Fri Nov 04, 2005 12:00 am
Location: Serbia

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

Post 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).
seph

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

Post 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...
seph

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

Post 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?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

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

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
seph

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

Post by seph »

The segment limits are 0xFFFFFFFF
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

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

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
seph

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

Post 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!
Post Reply