Failure in QEMU but not Bochs [solved]
Posted: Thu Jul 02, 2009 5:35 pm
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.
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.