Page 1 of 1

[SOLVED] Only receiving one RTC interrupt ...

Posted: Sat May 27, 2017 8:01 pm
by Izzette
I'm working on an RTC driver, and am only receiving one interrupt from it immediately after setting the IF flag. I've set the rate in CMOS RTC status register A and enabled RTC periodic interrupts in CMOS RTC status register B. I've unmasked IRQ2 and IRQ8, and have a valid IDT entry for IRQ8. I receive IRQ0 and IRQ1 just fine. I am reading the CMOS RTC status register C before enabling interrupts, and then again in my IRQ8 handler (before PIC EOI).

Here is the relevant code:
RTC configuration: https://github.com/Izzette/izix/blob/rt ... cmos/rtc.c
CMOS read/write functions: https://github.com/Izzette/izix/blob/rt ... mos/cmos.c
IRQ8 hook (and other stuff): https://github.com/Izzette/izix/blob/rt ... ock_tick.c

Thanks for your help! I'll add any code or debugging info you'd like to see.

Re: Only receiving one RTC interrupt ...

Posted: Sat May 27, 2017 8:57 pm
by MichaelPetch
Do you send an End of Interrupt (EOI) to the appropriate PIC before doing the IRET from your timer handler?

Re: Only receiving one RTC interrupt ...

Posted: Sat May 27, 2017 9:13 pm
by Izzette
Yeah, I send an EOI to the master in the IRQ0,1,3-7 handlers, and one to the slave in IRQ8-15 handlers, after re-enabling interrupts (I'm using interrupt gates not trap gates), but before IRET.

Re: Only receiving one RTC interrupt ...

Posted: Sat May 27, 2017 9:25 pm
by Brendan
Hi,
MichaelPetch wrote:Do you send an End of Interrupt (EOI) to the master PIC (Since you are dealing with IRQ0) before doing the IRET from your timer handler?
I think you're right.

Specifically, in pic_8259.c, this:

Code: Select all

void pic_8259_send_eoi (irq_t irq) {
	outb (PIC_EOI, pic_8259_get_pic_cmd_port (irq));
}
Probably needs to be more like this:

Code: Select all

void pic_8259_send_eoi (irq_t irq) {
    if (pic_8259_is_slave_irq (irq)) {
        outb (PIC_EOI, PIC_SLAVE_CMD);
    }
    outb (PIC_EOI, PIC_MASTER_CMD);
}

Cheers,

Brendan

Re: Only receiving one RTC interrupt ...

Posted: Sat May 27, 2017 9:38 pm
by Brendan
Hi,
Izzette wrote:Yeah, I send an EOI to the master in the IRQ0,1,3-7 handlers, and one to the slave in IRQ8-15 handlers, after re-enabling interrupts (I'm using interrupt gates not trap gates), but before IRET.
If the slave sees an IRQ, then it's a little bit like the slave triggers "IRQ2" on the master (except the master doesn't send the "interrupt vector" to the CPU and lets the slave send it); which means that you need to send an EOI to the slave (to clear its IRQ8) and then send an EOI to the master (to clear its IRQ2).

If you don't send EOI to master, then the PIC chip's "IRQ priorities" prevent lower priority IRQs (IRQs 8, 9, 10, 11, 12, 13, 14, 15, 3, 4, 5, 6 and 7) from being sent to the CPU, but higher priority IRQs (IRQs 0 and 1) do keep working.

Note: While browsing your code I also noticed that you don't handle spurious IRQs properly. If IRQ7 occurs you should ask the master PIC if it's a spurious IRQ and ignore it (without sending EOI) if it is; and if IRQ15 occurs you should ask the slave PIC if it's a spurious IRQ and if it is only send EOI to the master PIC but not the slave PIC.


Cheers,

Brendan

Re: Only receiving one RTC interrupt ...

Posted: Sat May 27, 2017 9:42 pm
by Izzette
It's strange, I'm still receiving IRQ0 and IRQ1, I'd think if I needed to send EOI to the master PIC I wouldn't receive those ... But, I'll make that change *fingers crossed*.
Yeah, I know I don't handle spurious IRQs, but I'm just using QEMU for now and they don't happen on virtual hardware (right?)

Re: Only receiving one RTC interrupt ...

Posted: Sat May 27, 2017 9:47 pm
by Izzette
That was it, I needed to send EOI to master and slave for IRQs from the slave PIC. I get my RTC interrupts now. Thanks so much for your time!

Re: Only receiving one RTC interrupt ...

Posted: Sun May 28, 2017 2:57 pm
by onlyonemac
It's probably not necessary, at least initially, to detect spurious IRQs. It's unlikely that anyone will be using either printer ports or ATA hard disks.

Re: Only receiving one RTC interrupt ...

Posted: Sun May 28, 2017 4:18 pm
by mikegonta
onlyonemac wrote:It's probably not necessary, at least initially, to detect spurious IRQs. It's unlikely that anyone will be using either printer ports or ATA hard disks.
A spurious interrupt is caused by electrical noise from the activity (usually high activity) of other interrupts and just happens (due to technical reasons)
to end up on IRQ 7 and has little to do with printers.

Re: Only receiving one RTC interrupt ...

Posted: Sun May 28, 2017 9:50 pm
by Brendan
Hi,
onlyonemac wrote:It's probably not necessary, at least initially, to detect spurious IRQs. It's unlikely that anyone will be using either printer ports or ATA hard disks.
The problem is that if an OS doesn't support spurious IRQs properly nasty things can happen (depending on how the OS is written). Some OSs could simply crash because IRQ7 or IRQ15 was masked in the PIC and there's no IRQ handler or IDT entry for IRQ7 or IRQ15. Some (most?) OSs would send an EOI for the spurious IRQ where the PIC thinks the EOI is for a completely unrelated IRQ, which can mean that the unrelated IRQ is "ended" before it's ever sent to the CPU (which can cause an unrelated device to get stuck in a "driver waiting for IRQ that never arrives" state where the device no longer works); or can cause an unrelated IRQ to be sent a second time causing further problems.

Fortunately it's easy to support spurious IRQs properly, for example maybe something like:

Code: Select all

IRQ7:
    push eax
    mov al,0x0B           ;al = "read ISR" command
    out 0x20,al           ;Send "read ISR" command
    in al,0x20            ;al = ISR for master PIC
    test al,0x80          ;Is it a spurious IRQ7?
    je .spuriousIRQ7      ; yes
    pop eax
    push dword 7          ;Put "IRQ number" on stack
    jmp commonIRQhandler

.spuriousIRQ7:
    inc dword [spuriousIRQ7counter]
    pop eax
    iret

IRQ15:
    push eax
    mov al,0x0B           ;al = "read ISR" command
    out 0xA0,al           ;Send "read ISR" command
    in al,0xA0            ;al = ISR for slave PIC
    test al,0x80          ;Is it a spurious IRQ15?
    je .spuriousIRQ15     ; yes
    pop eax
    push dword 15         ;Put "IRQ number" on stack
    jmp commonIRQhandler

.spuriousIRQ15:
    inc dword [spuriousIRQ15counter]
    mov al,0x20
    out 0x20,al           ;Send EOI to master PIC (but not slave)
    pop eax
    iret

Cheers,

Brendan

Re: Only receiving one RTC interrupt ...

Posted: Mon May 29, 2017 5:07 pm
by Izzette
Thanks, I'll make sure to handle spurious IRQs properly before I figure out why my bootloader is triple faulting on the one real computers I've tried it on ...