Failure in QEMU but not Bochs [solved]

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
Draust
Posts: 4
Joined: Thu Jul 02, 2009 5:18 pm

Failure in QEMU but not Bochs [solved]

Post by Draust »

Hello all; first post here. I *love* this site. I'm a fairly experienced applications-level programmer, but I've never written any OS-or-lower code (until the past few days!). Just to get a feel for things, I'm trying to write my own bootloader that goes from real -> protected -> long mode. I worked through the Babysteps tutorials (which were tremendously helpful), but I've run in to an issue I can't seem to resolve. The current setup I have is:

boot.asm - 512-byte 16-bit real mode code. Loads the second sector of my "floppy" (compiled boot32.asm) to memory location 0x7e00, enables protected mode (A20 line, GDT, cr0 bit), and far jumps to 0x7e00. (Side note - is this a sensible thing to do?)

boot32.asm - 512-byte 32-bit protected mode code. I can successfully write to 0xb8000 ("Hello from PMode!"). I'm trying to enable long mode. I'm mostly following the Entering Long Mode Directly (even though I've already enabled protected mode) for setting up the page tables and such. boot32.asm does:

- Print a status message.
- Set up PML4 / PDP / PD, with the PD identity-mapping the first 2 MB (a la the wiki article).
- Set the PAE / PGE flags in cr4.
- Set cr3 to the PML4 table address.
- Set IA-32e LME bit in the IA32_EFER MSR.
- Set the paging bit in cr0.
- Set IA-32e LMA bit in the IA32_EFER MSR.
- Jump to a 64-bit stub (just writes "Hello from Long Mode!" to 0xb8000).

My problem is that this code does not work in QEMU. When I'm stepping through execution with gdb, gdb starts to mess up immediately after I set the PAE / PGE flags in cr4. According to the QEMU log, I'm getting a page fault a few instructions farther down than that (specifically, where I read cr0 right before setting the paging bit). A few times before this I've run into issues I couldn't resolve just from gdb, and running the boot code through bochs was immensely helpful. In this case, the code works perfectly in bochs! It gets all the way down to printing the "Hello from Long Mode!". I assume that if my code doesn't work in QEMU, it's wrong somewhere... is bochs more forgiving about something?

Would posting code and/or log files help? I didn't want to spam too much junk on my first post. :)
Last edited by Draust on Fri Jul 03, 2009 10:30 am, edited 1 time in total.
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: Failure in QEMU but not Bochs

Post by 01000101 »

You should check to see if any reserved bits are set in your paging entries. Also, make sure you're setting the correct bits in the first place.
What version of BOCHS are you using? I'd grab the latest CVS of BOCHS and run your OS on that.

If you're still coming up empty, you could show us some of your paging setup code.
Draust
Posts: 4
Joined: Thu Jul 02, 2009 5:18 pm

Re: Failure in QEMU but not Bochs

Post by Draust »

Alright, running BOCHS CVS (with the debugger) now. I think maybe I don't understand how the GDT and paging interact. I follow the paging code from Entering Long Mode Directly basically exactly from "; Build Page Tables" onward. I think I'm successfully entering long mode; as soon as I set the paging bit in cr0, the LMA (Long Mode Active?) bit in EFER gets set by bochs. The very next instruction loads the gdt64; however, after that executes, every "disassemble" in the bochs debugger is preceded by:

WARNING: Offset 00007F0C is out of selector 0008 limit (00000000...00000000)!

Looking at the GDT that the long mode article sets up, it looks like it totally ignores the limit fields. I thought that was wrong, but the Wikipedia GDT article says that 64-bit selectors are always flat (0x0000000000000000 ... 0xffffffffffffffff). Does that mean that the limit field in the selectors can be left at zero? Is this possibly related to my problems in QEMU? What exactly does that bochs warning mean? Thanks!
Draust
Posts: 4
Joined: Thu Jul 02, 2009 5:18 pm

Re: Failure in QEMU but not Bochs

Post by Draust »

Hah, something I should've done a long time ago. The code in Entering Long Mode Directly fails for me in QEMU (0.10.0), but works in Bochs (2.4.1-cvs). It also fails in VirtualBox (the only log I get says "triple fault"). The detailed QEMU log is:

Code: Select all

Triple fault
CPU Reset (CPU 0)
EAX=00000100 EBX=e0000011 ECX=c0000080 EDX=00000000
ESI=ffff0000 EDI=0008d000 EBP=00000000 ESP=00007c00
EIP=00007c89 EFL=00000286 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0000 00000000 0000ffff 00009300
CS =0000 00000000 0000ffff 00009b0f
SS =0000 00000000 0000ffff 00009300
DS =0000 00000000 0000ffff 00009300
FS =0000 00000000 0000ffff 00009300
GS =0000 00000000 0000ffff 00009300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     000fb642 00000030
IDT=     00000000 000003ff
CR0=e0000011 CR2=00007c89 CR3=0000a000 CR4=000000a0
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000084 CCD=e0000011 CCO=EFLAGS  
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
It loops like EIP = CR2; that means there's a page fault, right? Is there something wrong with the code in that article?
JohnnyTheDon
Member
Member
Posts: 524
Joined: Sun Nov 09, 2008 2:55 am
Location: Pennsylvania, USA

Re: Failure in QEMU but not Bochs

Post by JohnnyTheDon »

I don't think you are running 64-bit qemu. Your registers are showing up as EAX,EBX, etc. when they should be RAX,RBX, etc.

Make sure you are running qemu-system-x86_64, not just qemu.
Draust
Posts: 4
Joined: Thu Jul 02, 2009 5:18 pm

Re: Failure in QEMU but not Bochs

Post by Draust »

Wow, you're exactly right. I feel dumb now. :) Thanks!
Post Reply