Incorrect Stack on IRET in IRQ0 Handler
Posted: Tue Aug 09, 2016 9:05 pm
So I am currently trying to re-enable interrupts in 32-bit mode, and I have run into a weird error that should be easily fixed.
I have currently set up my GDT and IDT in 32-bit mode, mapped IRQs 0-15 to IVT entries 32-47, and enabled both the 8259A PIC and 8253 PIT, enabling interrupts with "sti" afterwards.
However, upon the PIT firing IRQ0, the OS generates a General Protection Fault (IR 13). I have been debugging with both GDB and Bochs and I believe the issue is related to an incorrect stack, which should be easily solvable. When an IRQ that does not generate an error code is fired (such as IRQ0) EFLAGS, CS, then EIP is pushed to the stack. If an error code is fired, EFLAGS, CS, EIP, and the 32-bit error code is pushed.
In C, I have been using the following method to update ESP and to read the values from the stack before calling IRET:
(If an error code is generated, I also get that with movl 16(%%esp)).
I have checked the stack with bochs debugger (I can put a "for (;;) { asm("hlt"); } to halt the system) and I have found that it is not set up correctly.
Because I am still in Ring 0, the processor should use the current stack. But I have found 0x00000008 (my CS value, or at least what I think it is) to be offset 20-42 bytes from ESP instead of 4 bytes when handling an interrupt, and the location of different values in the stack also change frequently. I have looked through my code, and I am unable to figure out why in the world this is happening. It happens in QEMU, Bochs, and VirtualBox.
My GDT is set up correctly (Triple-checked it). IDT is also set up correctly and IRQs 0-15 are correctly mapped to 32-47 IRs. PIT and PIC are initialized correctly. Assembly code should be great for what I want it to do. I have researched the stack, even widely switch the values (from "movl 4(%%esp)" to "movl -4(%%esp)"), or adjusted ESP, but nothing seems to work. I have googled all over this site and the internet (looked as OSDev.org, BrokenThorn.com, even articles from .edu sites) but I cannot make heads or tails out of the problem. If there's a problem with the code, or it's clear for some reason that I don't fully understand the stack, please let me know. Any help possible would be greatly appreciated!
My source code can be found on GitHub here: https://github.com/jaller200/DarkOS. Thanks in advance for any guidance or help!
I have currently set up my GDT and IDT in 32-bit mode, mapped IRQs 0-15 to IVT entries 32-47, and enabled both the 8259A PIC and 8253 PIT, enabling interrupts with "sti" afterwards.
However, upon the PIT firing IRQ0, the OS generates a General Protection Fault (IR 13). I have been debugging with both GDB and Bochs and I believe the issue is related to an incorrect stack, which should be easily solvable. When an IRQ that does not generate an error code is fired (such as IRQ0) EFLAGS, CS, then EIP is pushed to the stack. If an error code is fired, EFLAGS, CS, EIP, and the 32-bit error code is pushed.
In C, I have been using the following method to update ESP and to read the values from the stack before calling IRET:
Code: Select all
asm("addl $12, %esp);
// ... Handle interrupt here
int eip;
int cs;
int eflags;
asm("movl (%%esp), %0" : "=r"(eip));
asm("movl 4(%%esp), %0" : "=r"(cs));
asm("movl 8(%%esp), %0" : "=r"(eflags));
// ... Print integers here
asm("iretl");
I have checked the stack with bochs debugger (I can put a "for (;;) { asm("hlt"); } to halt the system) and I have found that it is not set up correctly.
Because I am still in Ring 0, the processor should use the current stack. But I have found 0x00000008 (my CS value, or at least what I think it is) to be offset 20-42 bytes from ESP instead of 4 bytes when handling an interrupt, and the location of different values in the stack also change frequently. I have looked through my code, and I am unable to figure out why in the world this is happening. It happens in QEMU, Bochs, and VirtualBox.
My GDT is set up correctly (Triple-checked it). IDT is also set up correctly and IRQs 0-15 are correctly mapped to 32-47 IRs. PIT and PIC are initialized correctly. Assembly code should be great for what I want it to do. I have researched the stack, even widely switch the values (from "movl 4(%%esp)" to "movl -4(%%esp)"), or adjusted ESP, but nothing seems to work. I have googled all over this site and the internet (looked as OSDev.org, BrokenThorn.com, even articles from .edu sites) but I cannot make heads or tails out of the problem. If there's a problem with the code, or it's clear for some reason that I don't fully understand the stack, please let me know. Any help possible would be greatly appreciated!
My source code can be found on GitHub here: https://github.com/jaller200/DarkOS. Thanks in advance for any guidance or help!