I'm working on MIT's JOS (lab for 6.828 operating system class).
In this simple OS, interrupts are disabled in kernel mode (cli
is the first instruction run by the kernel). Interrupts are re-enabled once we launch a user process by setting up the eflags register accordingly, and should be somehow masked again when back to kernel mode.
My problem is that right after a trap occurs and that I'm back in kernel mode, IF is still set in eflags. I'm tempted to clear it using cli
as the first instruction of my trap handler, but the following comment (trap.c) explicitly says not to do it:
// Check that interrupts are disabled. If this assertion
// fails, DO NOT be tempted to fix it by inserting a "cli" in
// the interrupt path.
assert(!(read_eflags() & FL_IF));
I'm confused... is there another way to do it?
Yes, you can change the relevant entry in the IDT to make it an interrupt gate instead of a trap gate, which it is now. Then, whenever the interrupt is triggered, the CPU will automatically clear EFLAGS.IF when jumping to the handler and the flag will be restored when returning from the handler using IRETD.
My guess is that CLI won't help much because while it disables interrupts, it still allows nested interrupts and can potentially lead to a stack overflow. This little window of one instruction (CLI) where interrupts are still enabled is enough for a higher priority interrupt to intervene, which is, as I understand it, undesirable in the current implementation of the system or the task you're given.