[Solved] OS crashes on paging enable

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.
User avatar
BluCode
Posts: 22
Joined: Fri May 26, 2017 4:12 pm

Re: OS crashes on paging enable

Post by BluCode »

Thanks for clarifying, but that still doesn't solve the problem, which is still an issue if I set the R/W bits of the page table entries. Also could you explain how virtual address are translated into physical ones, as I don't quite understand the diagrams I've seen.
User avatar
iocoder
Member
Member
Posts: 208
Joined: Sun Oct 18, 2009 5:47 pm
Libera.chat IRC: iocoder
Location: Alexandria, Egypt | Ottawa, Canada
Contact:

Re: OS crashes on paging enable

Post by iocoder »

If you still don't understand the multi-level nature of page table hierarchy in x86, refer to this section on wikipedia: (https://en.wikipedia.org/wiki/Page_tabl ... page_table).

Say, for example, your program is going to access the logical address 0x00002ABC. Several calculations are handled first:
page index = 0x00002ABC>>12 = 0x00002.
DIR PAGE ENTRY INDX = 0x00002/1024 = 0
PG TBL ENTRY INDX = 0x00002%1024 = 2

Next, the i386 CPU turns attention to your page directory (which is stored at 0xD000 in your case). Entry i of the page directory gives us information about the page tables that covers the (i+1)th 4MB of logical memory. According to the calculations above, we should look at DIR PAGE ENTRY INDX 0, which contains 0x0000F007 in your case. This means that the page table that covers this part of memory exists at physical address 0x0000F000.

Finally, the i386 loads the addressed page table in TLB (if not loaded) and reads the desired PG TBL ENTRY from it. In our case, we want the entry that is located at index 2. This page table entry stores the value of 0x00002005, indicating that the physical address of the required page is 0x00002000, and hence the translation process would yield 0x00002ABC.

So, as you can see, translation is done over multiple stages. You can refer to section 5.2 of the manual for more illustration. The figures shall help you.

Best of luck!
User avatar
BluCode
Posts: 22
Joined: Fri May 26, 2017 4:12 pm

Re: OS crashes on paging enable

Post by BluCode »

Ah I see, that you very much. Do you have any ideas as to what could be causing the reboot cycle?
User avatar
iocoder
Member
Member
Posts: 208
Joined: Sun Oct 18, 2009 5:47 pm
Libera.chat IRC: iocoder
Location: Alexandria, Egypt | Ottawa, Canada
Contact:

Re: OS crashes on paging enable

Post by iocoder »

If you put a halting jump (asm("jmp .") as iansjack has suggested) just after you set the PE flag of cr0, what happens?
User avatar
BluCode
Posts: 22
Joined: Fri May 26, 2017 4:12 pm

Re: OS crashes on paging enable

Post by BluCode »

I see no change whatsoever, it still goes into the infinite reboot.
User avatar
iocoder
Member
Member
Posts: 208
Joined: Sun Oct 18, 2009 5:47 pm
Libera.chat IRC: iocoder
Location: Alexandria, Egypt | Ottawa, Canada
Contact:

Re: OS crashes on paging enable

Post by iocoder »

OK could you please show us a summary of the state of your registers just before you set the PE flags? you can use qemu's 'info registers' command for this purpose.
User avatar
BluCode
Posts: 22
Joined: Fri May 26, 2017 4:12 pm

Re: OS crashes on paging enable

Post by BluCode »

Here are the register values before enabling paging:

Code: Select all

EAX=00000011 EBX=00007d3c ECX=0000f000 EDX=0000830d
ESI=00000000 EDI=00000000 EBP=0008ffa0 ESP=0008ff90
EIP=00008505 EFL=00000286 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     0000b060 00000027
IDT=     0000b0a0 000007ff
CR0=00000011 CR2=00000000 CR3=0000d000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
EFER=0000000000000000
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
I could not figure out how to scroll the QEMU monitor, as ctrl+alt+pgup/pgdown didn't work, so I redirected it, but any input there would help as well.
User avatar
iocoder
Member
Member
Posts: 208
Joined: Sun Oct 18, 2009 5:47 pm
Libera.chat IRC: iocoder
Location: Alexandria, Egypt | Ottawa, Canada
Contact:

Re: OS crashes on paging enable

Post by iocoder »

BluCode wrote:Here are the register values before enabling paging:

Code: Select all

EAX=00000011 EBX=00007d3c ECX=0000f000 EDX=0000830d
ESI=00000000 EDI=00000000 EBP=0008ffa0 ESP=0008ff90
EIP=00008505 EFL=00000286 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     0000b060 00000027
IDT=     0000b0a0 000007ff
CR0=00000011 CR2=00000000 CR3=0000d000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
EFER=0000000000000000
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
I could not figure out how to scroll the QEMU monitor, as ctrl+alt+pgup/pgdown didn't work, so I redirected it, but any input there would help as well.
Thank you. Our first note here is the values of EBP and ESP. Do your identity page tables cover memory up to 0x8XXXX (above 512KB)?
User avatar
BluCode
Posts: 22
Joined: Fri May 26, 2017 4:12 pm

Re: OS crashes on paging enable

Post by BluCode »

Given that my first (and only) page table only has 16 frames, I would think not.

Code: Select all

(gdb) x 0xD000
0xd000: 0x0000f007
(gdb) x 0xf000
0xf000: 0x00000007
(gdb) x 0xf03c
0xf03c: 0x0000f007
(gdb) x 0xf040
0xf040: 0x00000000
I set up the stack to be very far from the kernel, and therefore very far from placement_address (_end from the linker). Is that good or bad, and why?
User avatar
iocoder
Member
Member
Posts: 208
Joined: Sun Oct 18, 2009 5:47 pm
Libera.chat IRC: iocoder
Location: Alexandria, Egypt | Ottawa, Canada
Contact:

Re: OS crashes on paging enable

Post by iocoder »

BluCode wrote:Given that my first (and only) page table only has 16 frames, I would think not.

Code: Select all

(gdb) x 0xD000
0xd000: 0x0000f007
(gdb) x 0xf000
0xf000: 0x00000007
(gdb) x 0xf03c
0xf03c: 0x0000f007
(gdb) x 0xf040
0xf040: 0x00000000
I set up the stack to be very far from the kernel, and therefore very far from placement_address (_end from the linker). Is that good or bad, and why?
The way you allocate your stack depends on your design philosophy, which is very subjective by its nature. But anyway, the problem here is that it is assigned a memory range that is higher than placement_address, in which case a PAGE FAULT will happen whenever your CPU tries to access the stack. Your identity maps should cover the stack as well, not just the kernel code and data.
Furthermore, could you please show me the code at which you use __asm__("jmp ."); after setting PE? what about this one:

Code: Select all

void switch_page_directory(page_directory_t *dir)
{
   current_directory = dir;
   asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));
   u32int cr0;
   asm volatile("mov %%cr0, %0": "=r"(cr0));
   cr0 |= 0x80000000; // Enable paging!
   asm volatile("mov %0, %%cr0; jmp .":: "r"(cr0)); // <-- can you see it? :D
}
User avatar
BluCode
Posts: 22
Joined: Fri May 26, 2017 4:12 pm

Re: OS crashes on paging enable

Post by BluCode »

I see. Yes I do my jump there, just in a new asm call. I'll probably not be able to try that change today as I am busy, but we'll see.
User avatar
iocoder
Member
Member
Posts: 208
Joined: Sun Oct 18, 2009 5:47 pm
Libera.chat IRC: iocoder
Location: Alexandria, Egypt | Ottawa, Canada
Contact:

Re: OS crashes on paging enable

Post by iocoder »

Take your time. I also forgot to mention that asynchronous interrupt requests that are issued by hardware in the background could also be fatal, since they make use of the stack.... which is actually not mapped. The result is that you end up with an infinite recursive page fault. You may want to disable interrupts before setting the PE flag, then enter the halting jump and see the results.

Code: Select all

void switch_page_directory(page_directory_t *dir)
{
   current_directory = dir;
   asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));
   u32int cr0;
   asm volatile("mov %%cr0, %0": "=r"(cr0));
   cr0 |= 0x80000000; // Enable paging!
   asm volatile("cli; mov %0, %%cr0; jmp .":: "r"(cr0)); // <-- disable interrupts; store cr0, then jmp forever.
}
As you can see, there are a lot of things to try out. Good luck with your debugging :D
User avatar
BluCode
Posts: 22
Joined: Fri May 26, 2017 4:12 pm

Re: OS crashes on paging enable

Post by BluCode »

It works! Turns out I just wasn't mapping enough of ram, even though the stack is under the kernel, and so was mapped. I tried disabling interrupts before enabling and that worked, but then I re-looked over my code and it turned out that my stack was at 7BFF and my kernel started at 7E00. Anyways I just identity mapped up to 16MB and now its working. Thanks for all your help!
User avatar
iocoder
Member
Member
Posts: 208
Joined: Sun Oct 18, 2009 5:47 pm
Libera.chat IRC: iocoder
Location: Alexandria, Egypt | Ottawa, Canada
Contact:

Re: OS crashes on paging enable

Post by iocoder »

BluCode wrote:It works! Turns out I just wasn't mapping enough of ram, even though the stack is under the kernel, and so was mapped. I tried disabling interrupts before enabling and that worked, but then I re-looked over my code and it turned out that my stack was at 7BFF and my kernel started at 7E00. Anyways I just identity mapped up to 16MB and now its working. Thanks for all your help!
According to the values of EBP and ESP, it seems that the stack (at the moment of setting cr0) is at 0x8FFFF, not at 0x7BFF. I suggest you check it out. We can conclude now that infinitely recursive page fault (IRPF) leads to CPU reset. However, I am still not sure about it. Needs more digging.
User avatar
BluCode
Posts: 22
Joined: Fri May 26, 2017 4:12 pm

Re: [Solved] OS crashes on paging enable

Post by BluCode »

It turns out that I didn't set esp and ebp in pm, just sp and bp in real mode. I set them in pm and now all is well, although ebp is slightly lower than I set it to, which is weird. (0x7bf3 instead of 0x7bff).
Post Reply