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:
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 |
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.
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] ...