diff --git a/Cargo.toml b/Cargo.toml index 03debdd..3f5878e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ version = "0.9.0" default-features = false [features] -default = [] +default = ["acpi", "multi_core"] acpi = [] doc = [] graphical_debug = [] diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs index 1317ba6..1a04789 100644 --- a/src/arch/x86_64/idt.rs +++ b/src/arch/x86_64/idt.rs @@ -68,9 +68,10 @@ pub unsafe fn init_paging() { IDT[46].set_func(irq::ata1); IDT[47].set_func(irq::ata2); - // Set IPI handler (null) - IDT[0x40].set_func(ipi::ipi); - IDT[0x41].set_func(ipi::pit); + // Set IPI handlers + IDT[0x40].set_func(ipi::wakeup); + IDT[0x41].set_func(ipi::tlb); + IDT[0x42].set_func(ipi::pit); // Set syscall function IDT[0x80].set_func(syscall::syscall); diff --git a/src/arch/x86_64/interrupt/ipi.rs b/src/arch/x86_64/interrupt/ipi.rs index 2f7177c..a0ad189 100644 --- a/src/arch/x86_64/interrupt/ipi.rs +++ b/src/arch/x86_64/interrupt/ipi.rs @@ -4,7 +4,7 @@ use context; use device::local_apic::LOCAL_APIC; use super::irq::PIT_TICKS; -interrupt!(ipi, { +interrupt!(wakeup, { LOCAL_APIC.eoi(); }); @@ -15,3 +15,7 @@ interrupt!(pit, { let _ = context::switch(); } }); + +interrupt!(tlb, { + LOCAL_APIC.eoi(); +}); diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs index 4031ed1..19a47c3 100644 --- a/src/arch/x86_64/interrupt/irq.rs +++ b/src/arch/x86_64/interrupt/irq.rs @@ -2,8 +2,9 @@ use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; use context; use context::timeout; -use device::{local_apic, pic}; +use device::pic; use device::serial::{COM1, COM2}; +use ipi::{ipi, IpiKind, IpiTarget}; use time; //resets to 0 in context::switch() @@ -40,9 +41,7 @@ pub unsafe fn acknowledge(irq: usize) { interrupt!(pit, { // Wake up other CPUs - if cfg!(feature = "multi_core") { - local_apic::LOCAL_APIC.set_icr(3 << 18 | 1 << 14 | 0x41); - } + ipi(IpiKind::Pit, IpiTarget::Other); // Saves CPU time by not sending IRQ event irq_trigger(0); diff --git a/src/arch/x86_64/ipi.rs b/src/arch/x86_64/ipi.rs new file mode 100644 index 0000000..021fc82 --- /dev/null +++ b/src/arch/x86_64/ipi.rs @@ -0,0 +1,28 @@ +#[derive(Clone, Copy, Debug)] +#[repr(u8)] +pub enum IpiKind { + Wakeup = 0x40, + Tlb = 0x41, + Pit = 0x42, +} + +#[derive(Clone, Copy, Debug)] +#[repr(u8)] +pub enum IpiTarget { + Current = 1, + All = 2, + Other = 3, +} + +#[cfg(not(feature = "multi_core"))] +#[inline(always)] +pub fn ipi(_kind: IpiKind, _target: IpiTarget) {} + +#[cfg(feature = "multi_core")] +#[inline(always)] +pub fn ipi(kind: IpiKind, target: IpiTarget) { + use device::local_apic::LOCAL_APIC; + + let icr = (target as u64) << 18 | 1 << 14 | (kind as u64); + unsafe { LOCAL_APIC.set_icr(icr) }; +} diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index b7857d2..715bcad 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -20,6 +20,9 @@ pub mod idt; /// Interrupt instructions pub mod interrupt; +/// Inter-processor interrupts +pub mod ipi; + /// Paging pub mod paging; diff --git a/src/arch/x86_64/paging/mod.rs b/src/arch/x86_64/paging/mod.rs index 395be8a..4f60fa8 100644 --- a/src/arch/x86_64/paging/mod.rs +++ b/src/arch/x86_64/paging/mod.rs @@ -5,6 +5,7 @@ use core::{mem, ptr}; use core::ops::{Deref, DerefMut}; use x86::shared::{control_regs, msr, tlb}; +use ipi::{ipi, IpiKind, IpiTarget}; use memory::{allocate_frames, Frame}; use self::entry::EntryFlags; diff --git a/src/context/context.rs b/src/context/context.rs index 0e4c87c..cc8037a 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -8,7 +8,7 @@ use spin::Mutex; use context::arch; use context::file::FileDescriptor; use context::memory::{Grant, Memory, SharedMemory, Tls}; -use device; +use ipi::{ipi, IpiKind, IpiTarget}; use scheme::{SchemeNamespace, FileHandle}; use syscall::data::SigAction; use syscall::flag::SIG_DFL; @@ -284,15 +284,14 @@ impl Context { pub fn unblock(&mut self) -> bool { if self.status == Status::Blocked { self.status = Status::Runnable; - if cfg!(feature = "multi_core") { - if let Some(cpu_id) = self.cpu_id { - if cpu_id != ::cpu_id() { - // Send IPI if not on current CPU - // TODO: Make this more architecture independent - unsafe { device::local_apic::LOCAL_APIC.set_icr(3 << 18 | 1 << 14 | 0x40) }; - } - } + + if let Some(cpu_id) = self.cpu_id { + if cpu_id != ::cpu_id() { + // Send IPI if not on current CPU + ipi(IpiKind::Wakeup, IpiTarget::Other); + } } + true } else { false