Hi,
What is the correct way to clear pending interrupt requests from the PIC? When I initialize my PIC handling code from a module there is a raise condition where an IRQ might happen before the module has been loaded in which case there is no handler for the IRQ and therefor a GPF will trigger instead. This is fine and is how I intended it to be.
The problem is that if this happens I need to send EOIs to the PICs after I have initialized and remapped them or else the PICs will continue to be in a "waiting for EOI state" and it will not continue to send more interrupts. Funny you would think configuring and remapping the PIC would clear pending interrupts but appearently it doesnt.
What I did to solve this problem was to look if the ISR for both PICs had any bit set and in that case I would send a EOI to that PIC. This worked perfectly. I'm just unsure if this is the correct way to handle it. To begin with it works for the IRR too but I just thought the ISR would make more sense. Also should I send an EOI for each set bit in the ISR (or IRR) or is just one EOI per PIC enough?
This is like the opposite of a spurious irq =) If anyone here has a good solution I'll add it to the wiki.
Correct way to clear pending interrupt requests?
Correct way to clear pending interrupt requests?
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
http://github.com/Jezze/fudge/
Re: Correct way to clear pending interrupt requests?
When you initialize the PIC (program the IRQ), it should return to clean state.
You can keep CLI for the cpu until the PIC handling code is ready, so anything happen after remap of PIC is pending until you re-enable interrupt with STI.
If you need to clear all "waiting for EOI state" you may also re-initialize the PIC anytime.
You can keep CLI for the cpu until the PIC handling code is ready, so anything happen after remap of PIC is pending until you re-enable interrupt with STI.
If you need to clear all "waiting for EOI state" you may also re-initialize the PIC anytime.
Re: Correct way to clear pending interrupt requests?
Yupp so I thought as well but this is not true it seems. At least not on a laptop I have where I need to manually send EOIs. Yes keeping CLI on is of course one way to handle this problem, the only issue there is that it would require my module to fiddle on the eflags register (since the load is done through a syscall and the flag would be reset upon return) so that is why I wanted to try out this other solution which felt more elegant =)
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
http://github.com/Jezze/fudge/
Re: Correct way to clear pending interrupt requests?
I have feeling that you're working on the wrong direction.Jezze wrote:that is why I wanted to try out this other solution which felt more elegant =)
Normal design you'll have IRQ handler with zero dependency, it should be isolated and will work without any driver is loaded.
You then design some sort of callback or queue interface for driver, and mechanism to handle EOI.
If a driver is not ready (or not exists) when IRQ occurs, the default handler should just skip that event and do EOI accordingly.
So, there is no need for workaround, since this kind of problem should not exist at all.
Re: Correct way to clear pending interrupt requests?
I understand where you are coming from but perhaps I'm just thinking out of the box here =) Do you mean to have the PIC code built into the kernel? I know all tutorials does this but I don't like that idea because to me the PIC is an extra piece of hardware and should not be part of the kernel by default because you might not need it which makes it a perfect candidate for a module. Also in my oppinion if you don't have anyone listening on a specific interrupt I dont think there should be a default stub to handle that because that is why the GPF exist to handle those cases.
I even have all the io functions like inb/inw/ind and outb/ouw/outd in a seperate module for this exact reason =)
I even have all the io functions like inb/inw/ind and outb/ouw/outd in a seperate module for this exact reason =)
Last edited by Jezze on Mon Jul 15, 2013 8:31 am, edited 1 time in total.
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
http://github.com/Jezze/fudge/
Re: Correct way to clear pending interrupt requests?
Hi,
Cheers,
Brendan
The problem occurs because:Jezze wrote:What is the correct way to clear pending interrupt requests from the PIC?
- You do CLI to disable IRQs
- One or more IRQs occur, causing the PIC to start trying to deliver the IRQ to the CPU (but it has to wait as IRQs are disabled with "CLI")
- You reprogram the PIC chips, causing them to forget about the IRQ/s they're still trying to deliver, and causing bits to be left set in the PIC's ISR/IRR
- You enable IRQs, but now bits are left set in the PIC's ISR/IRR that the PIC forgot about
- Mask all IRQs in the PIC; then give the firmware a chance to handle any IRQs that got received while you were doing that (e.g. do a few NOPs)
- After it's impossible for any bit in the PIC's IRR/ISR to be set; do CLI (to prevent spurious IRQs only)
- If one or more IRQs occur then they're masked and will be ignored by the PIC, and won't cause bits to be set in the PIC's ISR/IRR
- You reprogram the PIC
- You enable IRQs, and there can't be any bits left set in the PIC's ISR/IRR to mess things up
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: Correct way to clear pending interrupt requests?
Yupp, this is what I was looking for. Thanks! Yeah it is Grub I'm using, I don't think this will be a problem later on when I make my own bootloader.Brendan wrote:If you can't use the "most correct way" to prevent the problem (e.g. you're stuck with GRUB); then you'd need to do something to clear any bits in the PIC's ISR/IRR. This means masking all IRQs (so you don't get race conditions caused by receiving new IRQs while you're clearing out old ones); then doing something like "while( ISR_not_empty ) { sendEOI(); }" for each PIC chip.
As a side note: I can't mask them from the kernel because my kernel does not know about the io instructions, but the module with the PIC code can.
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
http://github.com/Jezze/fudge/