I'm developing a microkernel. In my kernel, there is a function which enables external interrupts. But it doesn't work. Then I realized that the instruction causing the problem is a sti followed by ret. Intel Software Developer Manual says:
If IF = 0, maskable hardware interrupts remain inhibited on the instruction boundary following an execution of STI. (The delayed effect of this instruction is provided to allow interrupts to be enabled just before returning from a procedure or subroutine. For instance, if an STI instruction is followed by an RET instruction, the RET instruction is allowed to execute before external interrupts are recognized. No interrupts can be recognized if an execution of CLI immediately follow such an execution of STI.) The inhibition ends after delivery of another event (e.g., exception) or the execution of the next instruction.
So interrupts should be enabled after the ret instruction, but that doesn't happen. IF in eflags in set, but no external interrupts. If I put a nop instruction between sti and ret, everything works.
Minimal reproducible example:
asm volatile ("call 1f;"
"jmp 2f;"
"1:"
"sti;"
// "nop;"
"ret;"
"2:");
Uncomment that nop, and interrupts would be enabled. Also, if I place one of the following line afters above, interrupts work:
asm volatile ("jecxz 1f; 1:");
asm volatile ("pushf; popf");
Note: I'm using QEMU to run my kernel.