Page 1 of 2

Paging

Posted: Fri Feb 14, 2003 4:22 pm
by chrisa128
At the minute Paging keeps crashing on me, can someone please give me a chacklist of what I need to do before enabling Paging???

I have included the information that BOCHS gave me for anyone that can understand it...

Code: Select all

00005904324p[CPU  ] >>PANIC<< exception(): 3rd (14) exception with no resolution
00005904324i[SYS  ] Last time is 1045261186
00005904324i[CPU  ] real mode
00005904324i[CPU  ] CS.d_b = 32 bit
00005904324i[CPU  ] SS.d_b = 32 bit
00005904324i[CPU  ] | EAX=80400000  EBX=80400000  ECX=000b8000  EDX=000003d5
00005904324i[CPU  ] | ESP=00108f78  EBP=00108fa8  ESI=00400000  EDI=0010582a
00005904324i[CPU  ] | IOPL=0 NV UP DI NG NZ NA PE NC
00005904324i[CPU  ] | SEG selector     base    limit G D
00005904324i[CPU  ] | SEG sltr(index|ti|rpl)     base    limit G D
00005904324i[CPU  ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00005904324i[CPU  ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00005904324i[CPU  ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00005904324i[CPU  ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00005904324i[CPU  ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00005904324i[CPU  ] |  CS:0018( 0003| 0|  0) 00000000 000fffff 1 1
00005904324i[CPU  ] | EIP=0010012f (0010012f)
00005904324i[CPU  ] | CR0=0x80400010 CR1=0x00000000 CR2=0x00108f76
00005904324i[CPU  ] | CR3=0x00400000 CR4=0x00000000
00005904324i[     ] restoring default signal behavior
00005904324i[CTRL ] quit_sim called with exit code 1
Please help someone, I been trying to fix this myself for a week now!

Re:Paging

Posted: Sat Feb 15, 2003 2:04 am
by Whatever5k
Do you have a page fault handler installed and enabled?
Did you set up a page directory and loaded it into CR3? Is the page directory page-aligned? Does the first entry of the page directory point to a page table? Are the PTE set up correctly?

Re:Paging

Posted: Sat Feb 15, 2003 7:39 am
by Ozguxxx
Also after making sure what abless told are satisfied you can do two things
to ensure consistent addressing before and after paging is enabled:
  • The page that is currently being executed should map to the same physical addresses both before and after PG is set.
  • A JMP instruction should immediately follow the setting of PG.

Re:Paging

Posted: Sat Feb 15, 2003 8:45 am
by chrisa128
Do you have a page fault handler installed and enabled?
My Page-Fault handler is set to a default handler that would just panic! It is enabled!!!
Did you set up a page directory and loaded it into CR3? Does the first entry of the page directory point to a page table? Are the PTE set up correctly?
This is where I think I am going wrong, here is the code...

Code: Select all

unsigned long *page_directory = (unsigned long *) 0x9C000;
unsigned long *page_table = (unsigned long *) 0x9D000;

void init_paging(void)
{
   unsigned long address=0;
   unsigned int i;
   kprintf("a");
   for (i=0; i<1024; i++)   {
      page_table[i] = address | 3;
      address = address + 4096;
   };
   kprintf("i");
   page_directory[0] = *page_table;
   page_directory[0] = page_directory[0] | 3;
   kprintf("k");
   i=1;   
   for (i=1; i<1024; i++)   {
      page_directory[i] = 0 | 2;
   };

   set_page_dir(*page_directory);
   set_page_bit(get_page_bit() | 0x80000000);
   kprintf("o");
}
The kprintf's are for debuggin, it doesn't reach the stage where it should print "o"!
The page that is currently being executed should map to the same physical addresses both before and after PG is set.
I am directly mapping the first 4Mb of memory and the kernel is loaded at 1Mb.
A JMP instruction should immediately follow the setting of PG.
I have done this I think....

Code: Select all

[GLOBAL _get_page_bit]
_get_page_bit
   mov eax,cr0
   retn

[GLOBAL _set_page_bit]
_set_page_bit
   push eax      
      mov eax,[esp + 8]
      mov cr0,eax
   pop eax
   jmp check1
check1:
   retn

[GLOBAL _get_page_dir]
_get_page_dir
   mov eax,cr3
   retn

[GLOBAL _set_page_dir]
_set_page_dir
   pusha
   push eax      
      mov eax,[esp + 4]
      mov cr3,eax
   jmp check2
check2:
   pop eax
   popa
   retn

Re:Paging

Posted: Sat Feb 15, 2003 11:54 am
by Whatever5k

Code: Select all

   page_directory[0] = *page_table;
   page_directory[0] = page_directory[0] | 3;
That is a bit wrong here - first of all, *page_table contains the value page_table is pointing to, but we want to have the address page_table is pointing to - that is just page_table without *.
Next, you don't set the access privileges for the page_table...
At last, page_directory[0] is wrong, too...same as above, that stands for the value - we need the address...
And why do you map the page directory into itself in entry 0. That would overwrite the previous mappnig (page_table)...
That is impossible to work correctly...better take 1023 as selfmapping entry...
So here's the correction:

Code: Select all

   page_directory[0] = page_table | 0x3;
   page_directory[1023] = page_directory | 0x3;
And there's a bug with your call to set_page_dir, too...
Do it like this:

Code: Select all

set_page_dir(page_directory);
Without the unary * like above...

Re:Paging

Posted: Sat Feb 15, 2003 12:27 pm
by chrisa128
Ok, made the changes you said and here's what I get

Code: Select all

   page_directory[0] = page_table | 0x3;
memory.c:52: invalid operands to binary |

Code: Select all

   set_page_dir(page_directory);
memory.c:59: warning: passing arg1 of 'set_page_dir' makes integer from pointer without a cast

These are the reasons I did what i did in the first place. Thanks for pointing out the self mapping, this was actually accidential.

Re:Paging

Posted: Sat Feb 15, 2003 12:50 pm
by Whatever5k
Ok, you have to use a cast...:

Code: Select all

page_directory[0] = (unsigned long) page_table | 0x3;
What did you declare set_page_dir() as in your prototype declarations? It should be that:

Code: Select all

void set_page_dir(unsigned long *);

Re:Paging

Posted: Sat Feb 15, 2003 1:31 pm
by chrisa128
It compiles, but still triple faults...

1. Have I got to enable the A20 address line before I enable paging and does Grub do this for you?

2. Can I enable the A20 gate in PMode

Re:Paging

Posted: Sat Feb 22, 2003 9:32 am
by chrisa128
Ok, I enabled the A20 and it still crashed but when I changed

Code: Select all

set_page_bit(get_page_bit() | 0x80000000);
to

Code: Select all

set_page_bit(get_page_bit() || 0x80000000);
It didn't triple fault, can anyone tell me if this means Paging is Enabled or if it failed to set the correct bit

Thanks

Re:Paging

Posted: Sun Feb 23, 2003 3:59 am
by Whatever5k
No, || is the logical OR-operator, it won't do what you want - paging isn't enabled...
GRUB enables the A20-Gate automatically for you, there's no need to worry about that if using GRUB...
Could you please post the whole code that is important for paging...?

Re:Paging

Posted: Sun Feb 23, 2003 3:53 pm
by chrisa128
Bit longer than it needs to be becuase of the debugging. The ASM bits are the same as above

Code: Select all

void init_paging(void)
{
   unsigned long address=0;
   unsigned int i;
   unsigned long u=0;
   //kprintf("a");
   for (i=0; i<1024; i++)   {
      page_table[i] = (unsigned long) address | 0x3;
      address = (unsigned long) address + 4096;
   };
   //kprintf("i");

   page_directory[0] = (unsigned long) page_table | 0x3;
   page_directory[1023] = (unsigned long) page_directory[0] | 0x3;
   //kprintf("k");

   for (i=1; i<1024; i++)   {
      page_directory[i] = 00 | 0x2;
   };

   set_page_dir(page_directory);
   //kprintf("x");

   u = (unsigned long) get_page_bit();
//   kprintf("\nCghros = %u",u);
   u = u || 0x80000000;
//   kprintf("\nCghr2332 = %u",u);
   set_page_bit(u || 0x80000000);
   //kprintf("o");
}
The defines are as follows

Code: Select all

unsigned get_page_dir(void);
unsigned get_page_bit(void);
void set_page_bit(unsigned long cr0);
void set_page_dir(unsigned long *);

unsigned long *page_directory = (unsigned long *) 0x9C000;
unsigned long *page_table = (unsigned long *) 0x9D000;
Thanks

Re:Paging

Posted: Mon Feb 24, 2003 1:26 am
by distantvoices
You have several odd things in your code:

u = (unsigned long) get_page_bit();
// kprintf("\nCghros = %u",u);
u = u || 0x80000000;
// kprintf("\nCghr2332 = %u",u);
set_page_bit(u || 0x80000000);
//kprintf("o");

this will not do the job you expect it to do:

because || is as previously stated by abless the logical or-operator. You have to set the highest bit in cr0 with bitwise OR. bitwise OR = "|"

thus shall it look like:
set_page_bit(get_page_bit()|0x80000000);

the second Thing I have seen:
for (i=1; i<1024; i++) {
page_directory = 00 | 0x2;
};

as you have entered your page_directory self mapping entry at pagedir[1024] you should avoid to overwrite it lter on:

for(i=1;i<1023;i++){ ... }

Re:Paging

Posted: Mon Feb 24, 2003 2:18 am
by Pype.Clicker
maybe the problem is in your set/get_page_* functions ...
Otherwise, the rest of the C code looks fine to me (provided that your data segment is 0-aligned, of course ;)

Re:Paging

Posted: Mon Feb 24, 2003 9:27 am
by chrisa128
provided that your data segment is 0-aligned,
I thought it had to be 4Kb aligned, with the following in my linker script.

Code: Select all

ALIGN 4096
Do you mean I got to align it to 0????

Re:Paging

Posted: Mon Feb 24, 2003 9:43 am
by Pype.Clicker
Pype.Clicker wrote: Otherwise, the rest of the C code looks fine to me (provided that your data segment is 0-aligned, of course ;)
oops.. i should have said "0-based" ... this is, DS.base == 0 in your GDT. Otherwise, the address of page_table as seen by C isn't the physical address of page_table and therefore, when the paging unit try to access physical address 0x9C000, it doesn't see the same memory array as what your code do with [ds:0x9c000] ...