[Solved] Returning to real mode from protected mode
Posted: Tue Dec 05, 2017 10:00 pm
Hello! I am new to OSdev. My question is in regard to returning to real mode.
Symptom:
I return to real mode, but when I call interrupts with the intention of running BIOS interrupt handlers, my system hangs (cursor in the top left of screen). This same behavior is observed on both Qemu as well as on my Thinkpad T410 Laptop. However, as long as I don’t execute the INT instruction in real mode, I can return back to protected mode and the execution makes it to my kernel’s main loop.
Details:
I am using the multiboot feature of GRUB as is suggested by OSDev tutorials. As soon my kernel is handed execution from GRUB, I believe the state to be in as what’s described in the multiboot specification (detailed here: https://www.gnu.org/software/grub/manua ... state.html). I have confirmed that this is the case by dumping registers as well as running gdb with Qemu.
State: Interrupts are disabled. I have not re-programmed the PIC or PIT yet. I have not enabled paging. I have statically defined two 16 bit entries in the GDT. I have a real mode interrupt descriptor that should be pointing to the BIOS’ IVT (0x00-0x3ff). I execute the following sequence of instructions:
1. Set %ebp and %esp to 0x7000
2. Load the GDT
3. Far jump to load the cs with the index of the descriptor -> 0x00009a000000ffff. (I have tried making entries in my normal GDT, as well as creating a second 0xffff limit only GDT)
4. Load rest of segment selectors with index of the data segment descriptor -> 0x00cf92000000ffff.
5. Load the real-mode IDT with the address of a memory location that contains the value -> 0x03ff00000000 . I thought the original IVT is at 0x00-0x3ff
6. Clear PE flag to return to real mode.
7. Far jump to real mode with cs segment selector as 0
8. Load ds,es,fs,gs,ss with 0’s
9. Enable interrupts.
10. Throw INT (it hangs here). If I don’t throw INT and let code re-enter protected mode I can make it to my kernel main. I am trying to run the meme820 test.
Resources:
Intel manual on Switching Back to Real-Address Mode, section 9.9.2: https://software.intel.com/sites/defaul ... -3abcd.pdf
OSDev tutorial on switching from protected real mode (http://wiki.osdev.org/Real_mode). However, this guide does not mention re-programming the PIC to the original setting. Due to the lack of this information, I am wondering if there are other “gotchas” for my case that I am missing.
Why do I want to return?
I want to interface with the BIOS for learning purposes. I feel that I should be able to return to real mode and am confused why I can’t get it to work. This indicates to me that I don’t understand something about my system’s state, and I am making some mistake or getting caught on a "gotcha." I would like to have this nailed down for a greater understanding. Does the multiboot specification trash the ivt?
I have tried to accurately capture my steps and was hoping to not post code just yet unless I am really stuck. Any help with this matter is appreciated
Symptom:
I return to real mode, but when I call interrupts with the intention of running BIOS interrupt handlers, my system hangs (cursor in the top left of screen). This same behavior is observed on both Qemu as well as on my Thinkpad T410 Laptop. However, as long as I don’t execute the INT instruction in real mode, I can return back to protected mode and the execution makes it to my kernel’s main loop.
Details:
I am using the multiboot feature of GRUB as is suggested by OSDev tutorials. As soon my kernel is handed execution from GRUB, I believe the state to be in as what’s described in the multiboot specification (detailed here: https://www.gnu.org/software/grub/manua ... state.html). I have confirmed that this is the case by dumping registers as well as running gdb with Qemu.
State: Interrupts are disabled. I have not re-programmed the PIC or PIT yet. I have not enabled paging. I have statically defined two 16 bit entries in the GDT. I have a real mode interrupt descriptor that should be pointing to the BIOS’ IVT (0x00-0x3ff). I execute the following sequence of instructions:
1. Set %ebp and %esp to 0x7000
2. Load the GDT
3. Far jump to load the cs with the index of the descriptor -> 0x00009a000000ffff. (I have tried making entries in my normal GDT, as well as creating a second 0xffff limit only GDT)
4. Load rest of segment selectors with index of the data segment descriptor -> 0x00cf92000000ffff.
5. Load the real-mode IDT with the address of a memory location that contains the value -> 0x03ff00000000 . I thought the original IVT is at 0x00-0x3ff
6. Clear PE flag to return to real mode.
7. Far jump to real mode with cs segment selector as 0
8. Load ds,es,fs,gs,ss with 0’s
9. Enable interrupts.
10. Throw INT (it hangs here). If I don’t throw INT and let code re-enter protected mode I can make it to my kernel main. I am trying to run the meme820 test.
Resources:
Intel manual on Switching Back to Real-Address Mode, section 9.9.2: https://software.intel.com/sites/defaul ... -3abcd.pdf
OSDev tutorial on switching from protected real mode (http://wiki.osdev.org/Real_mode). However, this guide does not mention re-programming the PIC to the original setting. Due to the lack of this information, I am wondering if there are other “gotchas” for my case that I am missing.
Why do I want to return?
I want to interface with the BIOS for learning purposes. I feel that I should be able to return to real mode and am confused why I can’t get it to work. This indicates to me that I don’t understand something about my system’s state, and I am making some mistake or getting caught on a "gotcha." I would like to have this nailed down for a greater understanding. Does the multiboot specification trash the ivt?
I have tried to accurately capture my steps and was hoping to not post code just yet unless I am really stuck. Any help with this matter is appreciated