From 11654456020c145d77a2c3729ff27663e7e7dcd3 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 20 Apr 2020 20:52:31 +0200 Subject: [PATCH] Add spurious IRQ handling, using a visible counter. --- src/arch/x86_64/device/pic.rs | 5 ++++ src/arch/x86_64/interrupt/irq.rs | 41 +++++++++++++++++++++++++------- src/scheme/sys/mod.rs | 2 ++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/arch/x86_64/device/pic.rs b/src/arch/x86_64/device/pic.rs index 2518550..12e68a6 100644 --- a/src/arch/x86_64/device/pic.rs +++ b/src/arch/x86_64/device/pic.rs @@ -70,4 +70,9 @@ impl Pic { mask &= !(1 << irq); self.data.write(mask); } + /// A bitmap of all currently servicing IRQs. Spurious IRQs will not have this bit set + pub fn isr(&mut self) -> u8 { + self.cmd.write(0x0A); + self.cmd.read() // note that cmd is read, rather than data + } } diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs index fe53f7a..e5f3c5a 100644 --- a/src/arch/x86_64/interrupt/irq.rs +++ b/src/arch/x86_64/interrupt/irq.rs @@ -1,5 +1,7 @@ use core::sync::atomic::{AtomicUsize, Ordering}; +use alloc::vec::Vec; + use crate::context::timeout; use crate::device::{local_apic, ioapic, pic}; use crate::device::serial::{COM1, COM2}; @@ -53,6 +55,27 @@ pub enum IrqMethod { Apic = 1, } +static SPURIOUS_COUNT_IRQ7: AtomicUsize = AtomicUsize::new(0); +static SPURIOUS_COUNT_IRQ15: AtomicUsize = AtomicUsize::new(0); + +pub fn spurious_count_irq7() -> usize { + SPURIOUS_COUNT_IRQ7.load(Ordering::Relaxed) +} +pub fn spurious_count_irq15() -> usize { + SPURIOUS_COUNT_IRQ15.load(Ordering::Relaxed) +} +pub fn spurious_count() -> usize { + spurious_count_irq7() + spurious_count_irq15() +} +pub fn spurious_irq_resource() -> syscall::Result> { + match irq_method() { + IrqMethod::Apic => Ok(Vec::from(&b"(not implemented for APIC yet)"[..])), + IrqMethod::Pic => { + Ok(format!("{}\tIRQ7\n{}\tIRQ15\n{}\ttotal\n", spurious_count_irq7(), spurious_count_irq15(), spurious_count()).into_bytes()) + } + } +} + static IRQ_METHOD: AtomicUsize = AtomicUsize::new(IrqMethod::Pic as usize); pub fn set_irq_method(method: IrqMethod) { @@ -120,16 +143,8 @@ unsafe fn pic_eoi(irq: u8) { if irq >= 8 { pic::MASTER.ack(); - if irq == 15 { - //TODO: check spurious - return; - } pic::SLAVE.ack(); } else { - if irq == 7 { - //TODO: check spurious - return; - } pic::MASTER.ack(); } } @@ -213,6 +228,11 @@ interrupt!(floppy, { }); interrupt!(lpt1, { + if pic::MASTER.isr() & (1 << 7) == 0 { + // the IRQ was spurious, ignore it but increment a counter. + SPURIOUS_COUNT_IRQ7.fetch_add(1, Ordering::Relaxed); + return; + } trigger(7); eoi(7); }); @@ -253,6 +273,11 @@ interrupt!(ata1, { }); interrupt!(ata2, { + if pic::SLAVE.isr() & (1 << 7) == 0 { + SPURIOUS_COUNT_IRQ15.fetch_add(1, Ordering::Relaxed); + pic::MASTER.ack(); + return + } trigger(15); eoi(15); }); diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs index d128b57..8b65632 100644 --- a/src/scheme/sys/mod.rs +++ b/src/scheme/sys/mod.rs @@ -9,6 +9,7 @@ use crate::syscall::data::Stat; use crate::syscall::error::{Error, EBADF, EINVAL, ENOENT, Result}; use crate::syscall::flag::{MODE_DIR, MODE_FILE, SEEK_CUR, SEEK_END, SEEK_SET}; use crate::syscall::scheme::Scheme; +use crate::arch::interrupt::irq; mod block; mod context; @@ -51,6 +52,7 @@ impl SysScheme { files.insert(b"scheme_num", Box::new(scheme_num::resource)); files.insert(b"syscall", Box::new(syscall::resource)); files.insert(b"uname", Box::new(uname::resource)); + files.insert(b"spurious_irq", Box::new(irq::spurious_irq_resource)); SysScheme { next_id: AtomicUsize::new(0),