Page 1 of 1
V8086 IRQ handling
Posted: Sun Mar 26, 2017 7:25 am
by Agola
Hi, I have multitasking and V8086 task support in my os. My V8086 monitor supports pushf, popf, int x, iret, outx, inx, cli and sti.
Then something pop into my head. As I didn't reprogrammed PICs, IRQs needs to be handled won't be handled as PIC doesn't redirect to IVT, it redirects IDT. So if some V8086 program needs IRQs, such as int 0x13 (for an example, I have already a native protected mode driver), the IRQs will get lost in V8086 handler.
If I reprogram PICs, this time I lose the other important IRQs, such as Ethernet.
What should I do to handle IRQs correctly both in V8086 and other tasks?
Thanks in advance.
Re: V8086 IRQ handling
Posted: Sun Mar 26, 2017 12:20 pm
by Brendan
Hi,
Agola wrote:What should I do to handle IRQs correctly both in V8086 and other tasks?
For a start, you should reprogram the PICs so that IRQ handlers don't conflict with exceptions.
The next problem is deciding what should handle an IRQ if/when it occurs. There are 3 cases:
- A native driver should handle the IRQ. For this case the V8086 task doesn't matter.
- The V8086 task should handle the IRQ. This has 3 sub-cases, where all of them involve some code in some sort of (protected mode) IRQ handling stub:
- The V8086 task is currently running with "pretend interrupts" enabled. In this case the "IRQ handling stub" can modify its own stack (so that the interrupt handler returns to the real mode IRQ handler) and also modify the V8086 mode stack (so that when the real mode IRQ handler returns it returns to the code that the "IRQ handling stub" interrupted).
- The V8086 task is currently running with "pretend interrupts" disabled, or the V8086 task is not currently running (e.g. the scheduler gave CPU time to a native task) with "pretend interrupts" disabled. In this case your "IRQ handling stub" needs to save some information somewhere (to remember that the IRQ occurred) and then return like normal. Later when the V8086 task does "STI" or "POPFD" (enabling IRQs) you get an general protection fault to emulate that instruction, and inject the postponed IRQ within the general protection fault handler (by modifying the general protection fault handler's stack and the V8086 code's stack, similar to before).
- The V8086 task is not currently running (e.g. a native task is using the CPU) and has "pretend interrupts" enabled. In this case your "IRQ handling stub" needs to save some information somewhere (to remember that the IRQ occurred) and then return like normal. Later when the scheduler does a task switch to the V8086 it needs to inject the postponed IRQ within the scheduler's task switch code (by modifying the kernel's stack and the V8086 code's stack, similar to before).
After the V8086 task has handled the IRQ it will send an EOI to either the master PIC or both PICs. When this happens you get another general protection fault (for an "outb" instruction) and you need to emulate this instruction by sending the EOI back to "whatever". Note that this can include sending an EOI back to an IO APIC because the kernel isn't using PIC chips at all (and it does not matter if the PIC chips are being used but have been reprogrammed).
- The IRQ is shared by 2 or more devices; where it needs to go to native drivers and the V8086 task. I'd recommend sending it to native all drivers first and designing your native drivers to return a "my device may could have/couldn't have caused this IRQ" status back; and then only sending it to V8086 if none of the native drivers say their device could have caused the IRQ.
Note that some devices will probably need to be "fully emulated" in software. This is likely to include the PIC chips themselves (in case real mode code tries to read the "Interrupt Received Register"/IRR or attempts reprogram the PIC chip/s or...), the PIT chip, and the RTC/CMOS.
Also note that there are a few features (added in Pentium CPUs?) that can make V8086 a little faster. One feature is "protected mode virtual interrupts" (which helps to emulate a "pretend/virtual interrupt enable/disable" flag). The other feature is something to do with reflecting IRQs back to the code running in V8086 mode (which is mainly intended for software interrupts - e.g. when a DOS program calls a DOS or BIOS function/interrupt).
Finally; I'd strongly recommend that if you simply don't bother.
There is no valid reason to want it in the first place (and for video mode switching, which is the only slightly tolerable excuse, there shouldn't be any IRQs involved).
Cheers,
Brendan