Paging

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

Paging

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

Re:Paging

Post 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?
Ozguxxx

Re:Paging

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

Re:Paging

Post 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
Whatever5k

Re:Paging

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

Re:Paging

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

Re:Paging

Post 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 *);
chrisa128

Re:Paging

Post 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
chrisa128

Re:Paging

Post 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
Whatever5k

Re:Paging

Post 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...?
chrisa128

Re:Paging

Post 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
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Re:Paging

Post 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++){ ... }
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Paging

Post 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 ;)
chrisa128

Re:Paging

Post 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????
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Paging

Post 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] ...
Post Reply