Page 1 of 1

IRQ1 continuous loop?

Posted: Fri Sep 17, 2021 6:22 pm
by YDeeps1
I recently setup exception interrupts and have now setup IRQs and (hopefully) mapped them to offsets 0x20 and 0x28 on the IDT with the help of the wiki (https://wiki.osdev.org/8259_PIC) post.

However, on offset 0x21 (index 33 in IDT which should be IRQ1), a continuous loop of IRQ1 interrupts occur right after acknowledging one after the other with a noticeable delay in between each interrupt log (around 70-130ms fluctuating off of the top of my head) which leads me to believe it may be a misconfigured PIT (I haven't touched the PIT yet)? Just curious if this is normal and/or if it can be adjusted/disabled. (I tried to find any sources on this but I couldn't which is why I'm making this post).

Thanks!

Re: IRQ1 continuous loop?

Posted: Fri Sep 17, 2021 7:03 pm
by Octocontrabass
The PIT is attached to IRQ0, not IRQ1, so it's definitely not the PIT.

It sounds like you've configured the PIC for level-triggered inputs (usually it should be edge-triggered) and you're also not acknowledging the device that drives the IRQ1 line: the keyboard controller.

Re: IRQ1 continuous loop?

Posted: Fri Sep 17, 2021 9:54 pm
by nullplan
One more note: You should probably mask out all interrupts (except IRQ 2, which is the cascading IRQ), and only unmask them in the drivers of the devices connected to them. This way, if you get an IRQ, you have some way to handle it, rather than just shrug. In the case of interrupt sharing, this can still leave you in an interrupting state, so the common advice is to mask out an interrupt that is occurring and only unmask it once it has been handled. If the interrupt handlers shrug at you, leave the interrupt disabled and continue booting. Hopefully you will drive the other devices on the line soon enough.

Re: IRQ1 continuous loop?

Posted: Sat Sep 18, 2021 4:35 am
by YDeeps1
Thank you for your inputs! And I apologise but it turns out I stupidly set the indexes wrong so those interrupts are actually from IRQ0, not IRQ1 (I have confirmed this with some test inputs). So could it still be the PIT (I masked it for now to avoid interruptions until I need them).

Re: IRQ1 continuous loop?

Posted: Sat Sep 18, 2021 5:23 pm
by Octocontrabass
In that case, it is the PIT.

Still, you should receive only one interrupt per tick, for a total of about 18 interrupts per second. From your description, it sounds like you were getting a lot more than that, which could mean you've configured the PIC for level-triggered interrupts when you were supposed to configure it for edge-triggered interrupts. (It's hard to say for sure since some virtual machines aren't very good at keeping time.)

Re: IRQ1 continuous loop?

Posted: Sun Sep 19, 2021 2:55 pm
by YDeeps1
Octocontrabass wrote:In that case, it is the PIT.

Still, you should receive only one interrupt per tick, for a total of about 18 interrupts per second. From your description, it sounds like you were getting a lot more than that, which could mean you've configured the PIC for level-triggered interrupts when you were supposed to configure it for edge-triggered interrupts. (It's hard to say for sure since some virtual machines aren't very good at keeping time.)
Actually after analysing it more, I'm actually getting more like 5 per second which definitely doesn't sound like the 18/s default.

I set the PIT to run at 18.222hz like it should anyways and it actually does speed up to the promised 18/s. Maybe the defaults are funky with VirtualBox? Anyways thank you guys!

Re: IRQ1 continuous loop?

Posted: Sun Sep 19, 2021 4:35 pm
by YDeeps1
And I don't want to make a new thread for this but just to confirm, if I would like to go slower than ~54ms per interrupt, would I have to use one shots to set my desired count downs?

Re: IRQ1 continuous loop?

Posted: Sun Sep 19, 2021 6:13 pm
by Octocontrabass
YDeeps1 wrote:Maybe the defaults are funky with VirtualBox?
Or VirtualBox has issues keeping time accurately, like most virtual machines.
YDeeps1 wrote:And I don't want to make a new thread for this but just to confirm, if I would like to go slower than ~54ms per interrupt, would I have to use one shots to set my desired count downs?
That's already the slowest it can go! If you need a longer delay, you'll have to either let the PIT interrupt you more than once or use a different timer.

Re: IRQ1 continuous loop?

Posted: Mon Sep 20, 2021 12:41 am
by YDeeps1
Thanks!

Re: IRQ1 continuous loop?

Posted: Mon Sep 20, 2021 5:30 pm
by thewrongchristian
YDeeps1 wrote:And I don't want to make a new thread for this but just to confirm, if I would like to go slower than ~54ms per interrupt, would I have to use one shots to set my desired count downs?
Exactly.

My timer is two layered. I have a platform specific timer, which has a one shot API, and specifies how long in microseconds the next call back needs to be. The platform specific layer then programs the timing source to call the callback using whatever mechanism the platform provides.

I only have a PIT provider at the moment, and as you've noticed, the longest timer that can provide is ~54ms (65535 cycles of the PIT 1193182Hz clock, but it can be 65536 cycles) So every PIT interrupt, I just subtract 65535 from however many cycles I have left. When that remaining time is less than 65535 cycles, reprogram the PIT timer to that number of cycles, then next interrupt, I fire the callback.

So, for example, to wait 1 second, I use the following sequence of PIT 1 shot timeouts:
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 65535
  • 13552
After this last interrupt, the callback is called, having waited 1193182 cycles (= 1 second). This layer can be easily replaced with some other one shot timer, such as the APIC timer.

The higher layer is just an ordered list of pending timers, sorted by interval to next time out. The upper layer timer just programs the lower layer to the interval at the head of the list, and waits for the callback.

It gets a little complicated, if halfway through waiting for this 1 second callback, another timer is started that would expire before the 1 second timer. Then, the lower level one shot is cancelled (we get back how long is left), and the new timer is scheduled instead. Then we can restart the 1 second timer, based on how long the intermediate timer was and how long we had left.