From cea95ee244f13ff229e91e8882d9661934101e11 Mon Sep 17 00:00:00 2001 From: Jonathan Klimt Date: Thu, 12 Mar 2026 17:02:57 +0100 Subject: [PATCH 1/4] docs(pci): specify pci irq lines reference --- src/drivers/pci.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/pci.rs b/src/drivers/pci.rs index bfd574c6b3..935ed380cf 100644 --- a/src/drivers/pci.rs +++ b/src/drivers/pci.rs @@ -172,7 +172,7 @@ impl PciDevice { None } 1..=4 => { - // PCI specification v3 footnote 43 + // PCI specification v3: Section 6.2.4 - footnote 43 #[cfg(target_arch = "x86_64")] if matches!(line, 16..254) { error!("Reserved IRQ number"); From 2b40e28b0db6109bf83e3d09d47f907205dc3be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Fri, 13 Mar 2026 13:56:21 +0100 Subject: [PATCH 2/4] refactor(pic): rename PIC_INTERRUPT_OFFSET to PIC_OFFSET --- src/arch/x86_64/kernel/pic.rs | 24 ++++++++++++++++++------ src/arch/x86_64/kernel/pit.rs | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/arch/x86_64/kernel/pic.rs b/src/arch/x86_64/kernel/pic.rs index 5eb87a7f71..a82779c93b 100644 --- a/src/arch/x86_64/kernel/pic.rs +++ b/src/arch/x86_64/kernel/pic.rs @@ -10,8 +10,20 @@ const PIC1_DATA: Port = Port::new(0x21); const PIC2_COMMAND: Port = Port::new(0xa0); const PIC2_DATA: Port = Port::new(0xa1); -pub const PIC1_INTERRUPT_OFFSET: u8 = 32; -const PIC2_INTERRUPT_OFFSET: u8 = 40; +/// PIC1 interrupt offset. +/// +/// Vectors 0 through 31 in the IDT are defined or reserved by the +/// architecture. Thus, user-defined interrupts are vectors 32 through 255. We +/// choose to map the 16 interrupts by the two PICs at the beginning of the +/// user-defined interrupts. +pub const PIC1_OFFSET: u8 = 32; + +/// PIC2 interrupt offset. +/// +/// Each PIC handles 8 interrupts. +/// We set up the two PICs to be contiguous. +const PIC2_OFFSET: u8 = 40; + const SPURIOUS_IRQ_NUMBER: u8 = 7; /// End-Of-Interrupt Command for an Intel 8259 Programmable Interrupt Controller (PIC). @@ -42,10 +54,10 @@ pub fn init() { // This is especially true for real hardware. So provide a handler for them. unsafe { let mut idt = IDT.lock(); - idt[PIC1_INTERRUPT_OFFSET + SPURIOUS_IRQ_NUMBER] + idt[PIC1_OFFSET + SPURIOUS_IRQ_NUMBER] .set_handler_fn(spurious_interrupt_on_master) .set_stack_index(0); - idt[PIC2_INTERRUPT_OFFSET + SPURIOUS_IRQ_NUMBER] + idt[PIC2_OFFSET + SPURIOUS_IRQ_NUMBER] .set_handler_fn(spurious_interrupt_on_slave) .set_stack_index(0); @@ -65,8 +77,8 @@ pub fn init() { pic2_command.write(0x11); // Map PIC1 to interrupt numbers >= 32 and PIC2 to interrupt numbers >= 40. - pic1_data.write(PIC1_INTERRUPT_OFFSET); - pic2_data.write(PIC2_INTERRUPT_OFFSET); + pic1_data.write(PIC1_OFFSET); + pic2_data.write(PIC2_OFFSET); // Configure PIC1 as master and PIC2 as slave. pic1_data.write(0x04); diff --git a/src/arch/x86_64/kernel/pit.rs b/src/arch/x86_64/kernel/pit.rs index 422808a2dd..90f4b50ac8 100644 --- a/src/arch/x86_64/kernel/pit.rs +++ b/src/arch/x86_64/kernel/pit.rs @@ -5,7 +5,7 @@ use x86_64::instructions::port::Port; use crate::arch::x86_64::kernel::pic; const PIT_CLOCK: u64 = 1_193_182; -pub const PIT_INTERRUPT_NUMBER: u8 = pic::PIC1_INTERRUPT_OFFSET; +pub const PIT_INTERRUPT_NUMBER: u8 = pic::PIC1_OFFSET; const PIT_CHANNEL0_DATA: Port = Port::new(0x40); const PIT_CHANNEL1_DATA: Port = Port::new(0x41); From 9eee5dadbdaf37ca5c006dafd167a31e959185bd Mon Sep 17 00:00:00 2001 From: Jonathan Klimt Date: Fri, 13 Mar 2026 14:01:21 +0100 Subject: [PATCH 3/4] refactor(pic): use offset constants more --- src/arch/x86_64/kernel/pic.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/arch/x86_64/kernel/pic.rs b/src/arch/x86_64/kernel/pic.rs index a82779c93b..7cefc9ef56 100644 --- a/src/arch/x86_64/kernel/pic.rs +++ b/src/arch/x86_64/kernel/pic.rs @@ -22,7 +22,7 @@ pub const PIC1_OFFSET: u8 = 32; /// /// Each PIC handles 8 interrupts. /// We set up the two PICs to be contiguous. -const PIC2_OFFSET: u8 = 40; +const PIC2_OFFSET: u8 = PIC1_OFFSET + 8; const SPURIOUS_IRQ_NUMBER: u8 = 7; @@ -114,8 +114,16 @@ extern "x86-interrupt" fn spurious_interrupt_on_slave(stack_frame: ExceptionStac } fn edit_mask(int_no: u8, insert: bool) { - let mut port = if int_no >= 40 { PIC2_DATA } else { PIC1_DATA }; - let offset = if int_no >= 40 { 40 } else { 32 }; + let mut port = if int_no >= PIC2_OFFSET { + PIC2_DATA + } else { + PIC1_DATA + }; + let offset = if int_no >= PIC2_OFFSET { + PIC2_OFFSET + } else { + PIC1_OFFSET + }; unsafe { let mask = port.read(); From ebba04edea2e558eb89f8ec352f57d9bef79fd2c Mon Sep 17 00:00:00 2001 From: Jonathan Klimt Date: Fri, 13 Mar 2026 14:29:48 +0100 Subject: [PATCH 4/4] fix(interrupts): only handle PIC interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Martin Kröning --- src/arch/x86_64/kernel/interrupts.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/arch/x86_64/kernel/interrupts.rs b/src/arch/x86_64/kernel/interrupts.rs index 5c4bc70da3..9f0a158089 100644 --- a/src/arch/x86_64/kernel/interrupts.rs +++ b/src/arch/x86_64/kernel/interrupts.rs @@ -13,6 +13,7 @@ use x86_64::structures::idt::InterruptDescriptorTable; pub use x86_64::structures::idt::InterruptStackFrame as ExceptionStackFrame; use crate::arch::x86_64::kernel::core_local::{core_scheduler, increment_irq_counter}; +use crate::arch::x86_64::kernel::pic::PIC1_OFFSET; use crate::arch::x86_64::kernel::{apic, processor}; use crate::arch::x86_64::mm::paging::{BasePageSize, PageSize, page_fault_handler}; use crate::arch::x86_64::swapgs; @@ -91,11 +92,12 @@ pub(crate) fn enable_and_wait() { pub(crate) fn install() { let mut idt = IDT.lock(); - set_general_handler!(&mut *idt, abort, 0..32); - set_general_handler!(&mut *idt, handle_interrupt, 32..); + set_general_handler!(&mut *idt, abort, 0..PIC1_OFFSET); + set_general_handler!(&mut *idt, handle_interrupt, PIC1_OFFSET..PIC1_OFFSET + 16); + set_general_handler!(&mut *idt, abort, PIC1_OFFSET + 16..); unsafe { - for i in 32..=255 { + for i in PIC1_OFFSET..PIC1_OFFSET + 16 { let addr = idt[i].handler_addr(); idt[i].set_handler_addr(addr).set_stack_index(0); } @@ -175,7 +177,7 @@ fn handle_interrupt(stack_frame: ExceptionStackFrame, index: u8, _error_code: Op use crate::scheduler::PerCoreSchedulerExt; if let Some(handlers) = IRQ_HANDLERS.get() - && let Some(map) = handlers.get(&(index - 32)) + && let Some(map) = handlers.get(&(index - PIC1_OFFSET)) { for handler in map.iter() { handler(); @@ -336,7 +338,7 @@ extern "x86-interrupt" fn virtualization_exception(stack_frame: ExceptionStackFr pub(crate) fn add_irq_name(irq_number: u8, name: &'static str) { debug!("Register name \"{name}\" for interrupt {irq_number}"); - IRQ_NAMES.lock().insert(32 + irq_number, name); + IRQ_NAMES.lock().insert(PIC1_OFFSET + irq_number, name); } fn get_irq_name(irq_number: u8) -> Option<&'static str> {