From 65e8abb449e8caec8d7358f29e6340814e07a050 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 14 Feb 2020 18:43:48 +0100 Subject: [PATCH 1/8] Allow multiple processes to share IRQs. I haven't been able to receive xhc interrupt anyway. --- src/scheme/irq.rs | 57 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index 60bcdd2..a238698 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -1,6 +1,8 @@ use core::{mem, str}; -use core::sync::atomic::Ordering; -use spin::Mutex; +use core::sync::atomic::{AtomicUsize, Ordering}; +use spin::{Mutex, RwLock}; + +use alloc::collections::BTreeMap; use crate::event; use crate::interrupt::irq::acknowledge; @@ -12,22 +14,42 @@ use crate::syscall::scheme::Scheme; pub static IRQ_SCHEME_ID: AtomicSchemeId = AtomicSchemeId::default(); /// IRQ queues -static ACKS: Mutex<[usize; 16]> = Mutex::new([0; 16]); static COUNTS: Mutex<[usize; 16]> = Mutex::new([0; 16]); +static HANDLES: RwLock>> = RwLock::new(None); /// Add to the input queue #[no_mangle] pub extern fn irq_trigger(irq: u8) { COUNTS.lock()[irq as usize] += 1; - event::trigger(IRQ_SCHEME_ID.load(Ordering::SeqCst), irq as usize, EVENT_READ); + + let guard = HANDLES.read(); + if let Some(handles) = guard.as_ref() { + for (fd, _) in handles.iter().filter(|(_, handle)| handle.irq == irq) { + event::trigger(IRQ_SCHEME_ID.load(Ordering::SeqCst), *fd, EVENT_READ); + } + } else { + println!("Calling IRQ without triggering"); + } } -pub struct IrqScheme; +struct Handle { + ack: AtomicUsize, + irq: u8, +} + +pub struct IrqScheme { + next_fd: AtomicUsize, +} impl IrqScheme { pub fn new(scheme_id: SchemeId) -> IrqScheme { IRQ_SCHEME_ID.store(scheme_id, Ordering::SeqCst); - IrqScheme + + *HANDLES.write() = Some(BTreeMap::new()); + + IrqScheme { + next_fd: AtomicUsize::new(0), + } } } @@ -39,7 +61,9 @@ impl Scheme for IrqScheme { let id = path_str.parse::().or(Err(Error::new(ENOENT)))?; if id < COUNTS.lock().len() { - Ok(id) + let fd = self.next_fd.fetch_add(1, Ordering::Relaxed); + HANDLES.write().as_mut().unwrap().insert(fd, Handle { ack: AtomicUsize::new(0), irq: id as u8 }); + Ok(fd) } else { Err(Error::new(ENOENT)) } @@ -51,9 +75,11 @@ impl Scheme for IrqScheme { fn read(&self, file: usize, buffer: &mut [u8]) -> Result { // Ensures that the length of the buffer is larger than the size of a usize if buffer.len() >= mem::size_of::() { - let ack = ACKS.lock()[file]; - let current = COUNTS.lock()[file]; - if ack != current { + let handles_guard = HANDLES.read(); + let handle = &handles_guard.as_ref().unwrap().get(&file).ok_or(Error::new(EBADF))?; + + let current = COUNTS.lock()[handle.irq as usize]; + if handle.ack.load(Ordering::SeqCst) != current { // Safe if the length of the buffer is larger than the size of a usize assert!(buffer.len() >= mem::size_of::()); unsafe { *(buffer.as_mut_ptr() as *mut usize) = current; } @@ -69,11 +95,16 @@ impl Scheme for IrqScheme { fn write(&self, file: usize, buffer: &[u8]) -> Result { if buffer.len() >= mem::size_of::() { assert!(buffer.len() >= mem::size_of::()); + + let handles_guard = HANDLES.read(); + let handle = &handles_guard.as_ref().unwrap().get(&file).ok_or(Error::new(EBADF))?; + let ack = unsafe { *(buffer.as_ptr() as *const usize) }; - let current = COUNTS.lock()[file]; + let current = COUNTS.lock()[handle.irq as usize]; + if ack == current { - ACKS.lock()[file] = ack; - unsafe { acknowledge(file); } + handle.ack.store(ack, Ordering::SeqCst); + unsafe { acknowledge(handle.irq as usize); } Ok(mem::size_of::()) } else { Ok(0) From c11d6d9e46038628946d01be2c63ff01585bf43f Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 15 Mar 2020 17:13:31 +0100 Subject: [PATCH 2/8] Update the x86 crate. --- Cargo.lock | 97 ++++++++++++++-------------- Cargo.toml | 2 +- src/arch/x86_64/device/local_apic.rs | 4 +- src/arch/x86_64/gdt.rs | 40 ++++++------ src/arch/x86_64/idt.rs | 4 +- src/arch/x86_64/interrupt/ipi.rs | 2 +- src/arch/x86_64/interrupt/syscall.rs | 4 +- src/arch/x86_64/paging/mod.rs | 10 +-- 8 files changed, 83 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dce7ae5..c09cb73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,18 +1,18 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "bitflags" -version = "0.7.0" +name = "bit_field" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.45" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -28,20 +28,20 @@ dependencies = [ name = "kernel" version = "0.1.54" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)", - "linked_list_allocator 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "linked_list_allocator 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "slab_allocator 0.3.1", "spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "x86 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "x86 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "linked_list_allocator" -version = "0.6.4" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -54,7 +54,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -62,18 +62,10 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "raw-cpuid" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -81,18 +73,28 @@ name = "raw-cpuid" version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "raw-cpuid" +version = "7.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" version = "0.1.56" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -131,24 +133,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.101" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.101" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "slab_allocator" version = "0.3.1" dependencies = [ - "linked_list_allocator 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "linked_list_allocator 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -164,11 +166,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "1.0.5" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -179,33 +181,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "x86" -version = "0.9.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" -"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" +"checksum bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a165d606cf084741d4ac3a28fb6e9b1eb0bd31f6cd999098cfddb0b2ab381dc0" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" "checksum goblin 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6a4013e9182f2345c6b7829b9ef6e670bce0dfca12c6f974457ed2160c2c7fe9" -"checksum linked_list_allocator 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "47314ec1d29aa869ee7cb5a5be57be9b1055c56567d59c3fb6689926743e0bea" +"checksum linked_list_allocator 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "47de1a43fad0250ee197e9e124e5b5deab3d7b39d4428ae8a6d741ceb340c362" "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" -"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13b844e4049605ff38fed943f5c7b2c691fad68d9d5bf074d2720554c4e48246" +"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" "checksum raw-cpuid 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "90e0d3209fac374e168cef2d8806dde7b31ef0ee82a965bcc0bec562c078a6f5" +"checksum raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4a349ca83373cfa5d6dbb66fd76e58b2cca08da71a5f6400de0a0a6a9bceeaf" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" -"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" +"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" "checksum spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum x86 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "178718d3f2c7dd98d44f8e353b0ccc8c89b2e81e31e5eed93e7fdf5f36db7a13" +"checksum x86 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6874753c331118b83f24d69325958b61f8ef47dbbc7aff2257a0bbe33fb24e3b" diff --git a/Cargo.toml b/Cargo.toml index d5348af..d750a8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ version = "0.1.13" default-features = false [dependencies.x86] -version = "0.9.0" +version = "0.29.0" default-features = false [features] diff --git a/src/arch/x86_64/device/local_apic.rs b/src/arch/x86_64/device/local_apic.rs index b08956e..9853686 100644 --- a/src/arch/x86_64/device/local_apic.rs +++ b/src/arch/x86_64/device/local_apic.rs @@ -1,6 +1,6 @@ use core::intrinsics::{volatile_load, volatile_store}; -use x86::shared::cpuid::CpuId; -use x86::shared::msr::*; +use x86::cpuid::CpuId; +use x86::msr::*; use crate::memory::Frame; use crate::paging::{ActivePageTable, PhysicalAddress, Page, VirtualAddress}; diff --git a/src/arch/x86_64/gdt.rs b/src/arch/x86_64/gdt.rs index cc56c3e..f5c950c 100644 --- a/src/arch/x86_64/gdt.rs +++ b/src/arch/x86_64/gdt.rs @@ -1,12 +1,12 @@ //! Global descriptor table use core::mem; -use x86::current::segmentation::set_cs; -use x86::current::task::TaskStateSegment; -use x86::shared::PrivilegeLevel; -use x86::shared::dtables::{self, DescriptorTablePointer}; -use x86::shared::segmentation::{self, SegmentDescriptor, SegmentSelector}; -use x86::shared::task; +use x86::segmentation::load_cs; +use x86::bits64::task::TaskStateSegment; +use x86::Ring; +use x86::dtables::{self, DescriptorTablePointer}; +use x86::segmentation::{self, Descriptor as SegmentDescriptor, SegmentSelector}; +use x86::task; use crate::paging::PAGE_SIZE; @@ -120,12 +120,12 @@ pub unsafe fn init() { dtables::lgdt(&INIT_GDTR); // Load the segment descriptors - set_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16, PrivilegeLevel::Ring0)); - segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0)); - segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0)); - segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0)); - segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0)); - segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0)); + load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16, Ring::Ring0)); + segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16, Ring::Ring0)); + segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16, Ring::Ring0)); + segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_DATA as u16, Ring::Ring0)); + segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16, Ring::Ring0)); + segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16, Ring::Ring0)); } /// Initialize GDT with TLS @@ -137,7 +137,7 @@ pub unsafe fn init_paging(tcb_offset: usize, stack_offset: usize) { dtables::lgdt(&INIT_GDTR); // Load the segment descriptors - segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16, PrivilegeLevel::Ring0)); + segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16, Ring::Ring0)); // Now that we have access to thread locals, setup the AP's individual GDT GDTR.limit = (GDT.len() * mem::size_of::() - 1) as u16; @@ -160,15 +160,15 @@ pub unsafe fn init_paging(tcb_offset: usize, stack_offset: usize) { dtables::lgdt(&GDTR); // Reload the segment descriptors - set_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16, PrivilegeLevel::Ring0)); - segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0)); - segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0)); - segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16, PrivilegeLevel::Ring0)); - segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0)); - segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0)); + load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16, Ring::Ring0)); + segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16, Ring::Ring0)); + segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16, Ring::Ring0)); + segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16, Ring::Ring0)); + segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16, Ring::Ring0)); + segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16, Ring::Ring0)); // Load the task register - task::load_tr(SegmentSelector::new(GDT_TSS as u16, PrivilegeLevel::Ring0)); + task::load_tr(SegmentSelector::new(GDT_TSS as u16, Ring::Ring0)); } #[derive(Copy, Clone, Debug)] diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs index 1a1d644..50ff92d 100644 --- a/src/arch/x86_64/idt.rs +++ b/src/arch/x86_64/idt.rs @@ -1,6 +1,6 @@ use core::mem; -use x86::current::irq::IdtEntry as X86IdtEntry; -use x86::shared::dtables::{self, DescriptorTablePointer}; +use x86::segmentation::Descriptor as X86IdtEntry; +use x86::dtables::{self, DescriptorTablePointer}; use crate::interrupt::*; use crate::ipi::IpiKind; diff --git a/src/arch/x86_64/interrupt/ipi.rs b/src/arch/x86_64/interrupt/ipi.rs index 18113c2..eb747e6 100644 --- a/src/arch/x86_64/interrupt/ipi.rs +++ b/src/arch/x86_64/interrupt/ipi.rs @@ -1,5 +1,5 @@ use core::sync::atomic::Ordering; -use x86::shared::tlb; +use x86::tlb; use crate::context; use crate::device::local_apic::LOCAL_APIC; diff --git a/src/arch/x86_64/interrupt/syscall.rs b/src/arch/x86_64/interrupt/syscall.rs index dd6b812..f084f4c 100644 --- a/src/arch/x86_64/interrupt/syscall.rs +++ b/src/arch/x86_64/interrupt/syscall.rs @@ -2,13 +2,13 @@ use crate::arch::macros::InterruptStack; use crate::arch::{gdt, pti}; use crate::syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_PRE_SYSCALL, PTRACE_STOP_POST_SYSCALL}; use crate::{ptrace, syscall}; -use x86::shared::msr; +use x86::msr; pub unsafe fn init() { msr::wrmsr(msr::IA32_STAR, ((gdt::GDT_KERNEL_CODE as u64) << 3) << 32); msr::wrmsr(msr::IA32_LSTAR, syscall_instruction as u64); msr::wrmsr(msr::IA32_FMASK, 0x0300); // Clear trap flag and interrupt enable - msr::wrmsr(msr::IA32_KERNEL_GS_BASE, &gdt::TSS as *const _ as u64); + msr::wrmsr(msr::IA32_KERNEL_GSBASE, &gdt::TSS as *const _ as u64); let efer = msr::rdmsr(msr::IA32_EFER); msr::wrmsr(msr::IA32_EFER, efer | 1); diff --git a/src/arch/x86_64/paging/mod.rs b/src/arch/x86_64/paging/mod.rs index 4221cc6..c4acb93 100644 --- a/src/arch/x86_64/paging/mod.rs +++ b/src/arch/x86_64/paging/mod.rs @@ -4,7 +4,7 @@ use core::ops::{Deref, DerefMut}; use core::{mem, ptr}; use spin::Mutex; -use x86::shared::{control_regs, msr, tlb}; +use x86::{controlregs, msr, tlb}; use crate::memory::{allocate_frames, Frame}; @@ -396,11 +396,11 @@ impl ActivePageTable { pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { let old_table = InactivePageTable { p4_frame: Frame::containing_address(PhysicalAddress::new( - unsafe { control_regs::cr3() } as usize, + unsafe { controlregs::cr3() } as usize, )), }; unsafe { - control_regs::cr3_write(new_table.p4_frame.start_address().get() as u64); + controlregs::cr3_write(new_table.p4_frame.start_address().get() as u64); } old_table } @@ -427,7 +427,7 @@ impl ActivePageTable { { { let backup = Frame::containing_address(PhysicalAddress::new(unsafe { - control_regs::cr3() as usize + controlregs::cr3() as usize })); // map temporary_page to current p4 table @@ -459,7 +459,7 @@ impl ActivePageTable { } pub unsafe fn address(&self) -> usize { - control_regs::cr3() as usize + controlregs::cr3() as usize } } From c154effd1cddefb501e26053dfc74eb76a2efdde Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 15 Mar 2020 16:51:10 +0100 Subject: [PATCH 3/8] Get a working local apic timer. --- src/arch/x86_64/device/local_apic.rs | 99 ++++++++++++++++++++++++++++ src/arch/x86_64/idt.rs | 2 + src/arch/x86_64/interrupt/irq.rs | 13 +++- 3 files changed, 113 insertions(+), 1 deletion(-) diff --git a/src/arch/x86_64/device/local_apic.rs b/src/arch/x86_64/device/local_apic.rs index 9853686..4cf332f 100644 --- a/src/arch/x86_64/device/local_apic.rs +++ b/src/arch/x86_64/device/local_apic.rs @@ -47,6 +47,8 @@ impl LocalApic { } else { self.write(0xF0, 0x100); } + self.setup_error_int(); + self.setup_timer(); } unsafe fn read(&self, reg: u32) -> u32 { @@ -113,4 +115,101 @@ impl LocalApic { self.write(0xB0, 0); } } + /// Reads the Error Status Register. + pub unsafe fn esr(&mut self) -> u32 { + if self.x2 { + // update the ESR to the current state of the local apic. + wrmsr(IA32_X2APIC_ESR, 0); + // read the updated value + rdmsr(IA32_X2APIC_ESR) as u32 + } else { + self.write(0x280, 0); + self.read(0x280) + } + } + pub unsafe fn lvt_timer(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_LVT_TIMER) as u32 + } else { + self.read(0x320) + } + } + pub unsafe fn set_lvt_timer(&mut self, value: u32) { + if self.x2 { + wrmsr(IA32_X2APIC_LVT_TIMER, u64::from(value)); + } else { + self.write(0x320, value); + } + } + pub unsafe fn init_count(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_INIT_COUNT) as u32 + } else { + self.read(0x380) + } + } + pub unsafe fn set_init_count(&mut self, initial_count: u32) { + if self.x2 { + wrmsr(IA32_X2APIC_INIT_COUNT, u64::from(initial_count)); + } else { + self.write(0x380, initial_count); + } + } + pub unsafe fn cur_count(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_CUR_COUNT) as u32 + } else { + self.read(0x390) + } + } + pub unsafe fn div_conf(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_DIV_CONF) as u32 + } else { + self.read(0x3E0) + } + } + pub unsafe fn set_div_conf(&mut self, div_conf: u32) { + if self.x2 { + wrmsr(IA32_X2APIC_DIV_CONF, u64::from(div_conf)); + } else { + self.write(0x3E0, div_conf); + } + } + pub unsafe fn lvt_error(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_LVT_ERROR) as u32 + } else { + self.read(0x370) + } + } + pub unsafe fn set_lvt_error(&mut self, lvt_error: u32) { + if self.x2 { + wrmsr(IA32_X2APIC_LVT_ERROR, u64::from(lvt_error)); + } else { + self.write(0x370, lvt_error); + } + } + unsafe fn setup_error_int(&mut self) { + let vector = 49u32; + self.set_lvt_error(vector); + } + unsafe fn setup_timer(&mut self) { + let div_conf_value = 0b1010; // divide by 128 + self.set_div_conf(div_conf_value); + + let init_count_value = 1_000_000; + self.set_init_count(init_count_value); + + let lvt_timer_value = ((LvtTimerMode::Periodic as u32) << 17) | 48u32; + self.set_lvt_timer(lvt_timer_value); + + // TODO: Get the correct frequency, use the local apic timer instead of the PIT. + } +} +#[repr(u8)] +pub enum LvtTimerMode { + OneShot = 0b00, + Periodic = 0b01, + TscDeadline = 0b10, } diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs index 50ff92d..7ca296d 100644 --- a/src/arch/x86_64/idt.rs +++ b/src/arch/x86_64/idt.rs @@ -69,6 +69,8 @@ pub unsafe fn init_paging() { IDT[45].set_func(irq::fpu); IDT[46].set_func(irq::ata1); IDT[47].set_func(irq::ata2); + IDT[48].set_func(irq::lapic_timer); + IDT[49].set_func(irq::lapic_error); // Set IPI handlers IDT[IpiKind::Wakeup as usize].set_func(ipi::wakeup); diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs index 09ebf75..632cd4f 100644 --- a/src/arch/x86_64/interrupt/irq.rs +++ b/src/arch/x86_64/interrupt/irq.rs @@ -1,7 +1,7 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use crate::context::timeout; -use crate::device::pic; +use crate::device::{local_apic, pic}; use crate::device::serial::{COM1, COM2}; use crate::ipi::{ipi, IpiKind, IpiTarget}; use crate::scheme::debug::debug_input; @@ -29,6 +29,9 @@ unsafe fn trigger(irq: u8) { irq_trigger(irq); } +unsafe fn lapic_eoi() { + local_apic::LOCAL_APIC.eoi() +} pub unsafe fn acknowledge(irq: usize) { if irq < 16 { @@ -132,3 +135,11 @@ interrupt!(ata1, { interrupt!(ata2, { trigger(15); }); +interrupt!(lapic_timer, { + println!("Local apic timer interrupt"); + lapic_eoi(); +}); +interrupt!(lapic_error, { + println!("Local apic internal error: ESR={:#0x}", local_apic::LOCAL_APIC.esr()); + lapic_eoi(); +}); From 772003138d7ff54db311d0da83a828fa4dc9d7dd Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 20 Mar 2020 18:51:36 +0100 Subject: [PATCH 4/8] Add a backwards-compatible interface for more IRQs. --- Cargo.lock | 66 +++---- src/arch/x86_64/device/local_apic.rs | 126 ++++++++++++- src/arch/x86_64/idt.rs | 78 ++++++++ src/arch/x86_64/interrupt/irq.rs | 33 ++++ src/arch/x86_64/interrupt/mod.rs | 3 + src/arch/x86_64/macros.rs | 52 ++++++ src/arch/x86_64/mod.rs | 7 +- src/scheme/irq.rs | 256 ++++++++++++++++++++++----- 8 files changed, 534 insertions(+), 87 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c09cb73..ce392fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,12 +7,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.50" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -28,9 +28,9 @@ dependencies = [ name = "kernel" version = "0.1.54" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)", - "linked_list_allocator 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "linked_list_allocator 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -41,7 +41,7 @@ dependencies = [ [[package]] name = "linked_list_allocator" -version = "0.6.6" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -54,7 +54,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -62,10 +62,10 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -73,11 +73,11 @@ name = "raw-cpuid" version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -85,8 +85,8 @@ name = "raw-cpuid" version = "7.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -94,7 +94,7 @@ dependencies = [ name = "redox_syscall" version = "0.1.56" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -133,24 +133,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.104" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.104" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "slab_allocator" version = "0.3.1" dependencies = [ - "linked_list_allocator 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "linked_list_allocator 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -166,11 +166,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "1.0.16" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -185,19 +185,19 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] "checksum bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a165d606cf084741d4ac3a28fb6e9b1eb0bd31f6cd999098cfddb0b2ab381dc0" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" +"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" +"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" "checksum goblin 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6a4013e9182f2345c6b7829b9ef6e670bce0dfca12c6f974457ed2160c2c7fe9" -"checksum linked_list_allocator 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "47de1a43fad0250ee197e9e124e5b5deab3d7b39d4428ae8a6d741ceb340c362" +"checksum linked_list_allocator 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "47314ec1d29aa869ee7cb5a5be57be9b1055c56567d59c3fb6689926743e0bea" "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" -"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" -"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum raw-cpuid 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "90e0d3209fac374e168cef2d8806dde7b31ef0ee82a965bcc0bec562c078a6f5" "checksum raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4a349ca83373cfa5d6dbb66fd76e58b2cca08da71a5f6400de0a0a6a9bceeaf" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" @@ -205,10 +205,10 @@ dependencies = [ "checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" -"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" +"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" "checksum spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum x86 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6874753c331118b83f24d69325958b61f8ef47dbbc7aff2257a0bbe33fb24e3b" diff --git a/src/arch/x86_64/device/local_apic.rs b/src/arch/x86_64/device/local_apic.rs index 4cf332f..03565cf 100644 --- a/src/arch/x86_64/device/local_apic.rs +++ b/src/arch/x86_64/device/local_apic.rs @@ -1,3 +1,4 @@ +use core::sync::atomic::{self, AtomicU64}; use core::intrinsics::{volatile_load, volatile_store}; use x86::cpuid::CpuId; use x86::msr::*; @@ -5,6 +6,7 @@ use x86::msr::*; use crate::memory::Frame; use crate::paging::{ActivePageTable, PhysicalAddress, Page, VirtualAddress}; use crate::paging::entry::EntryFlags; +use crate::{interrupt, time}; pub static mut LOCAL_APIC: LocalApic = LocalApic { address: 0, @@ -25,6 +27,21 @@ pub struct LocalApic { pub x2: bool } +#[derive(Debug)] +struct NoFreqInfo; + +static BSP_APIC_ID: AtomicU64 = AtomicU64::new(0xFFFF_FFFF_FFFF_FFFF); + +#[no_mangle] +pub fn bsp_apic_id() -> Option { + let value = BSP_APIC_ID.load(atomic::Ordering::SeqCst); + if value <= u64::from(u32::max_value()) { + Some(value as u32) + } else { + None + } +} + impl LocalApic { unsafe fn init(&mut self, active_table: &mut ActivePageTable) { self.address = (rdmsr(IA32_APIC_BASE) as usize & 0xFFFF_0000) + crate::KERNEL_OFFSET; @@ -38,6 +55,7 @@ impl LocalApic { } self.init_ap(); + BSP_APIC_ID.store(u64::from(self.id()), atomic::Ordering::SeqCst); } unsafe fn init_ap(&mut self) { @@ -48,7 +66,7 @@ impl LocalApic { self.write(0xF0, 0x100); } self.setup_error_int(); - self.setup_timer(); + //self.setup_timer(); } unsafe fn read(&self, reg: u32) -> u32 { @@ -194,9 +212,36 @@ impl LocalApic { let vector = 49u32; self.set_lvt_error(vector); } - unsafe fn setup_timer(&mut self) { - let div_conf_value = 0b1010; // divide by 128 - self.set_div_conf(div_conf_value); + unsafe fn setup_timer(&mut self) -> Result<(), NoFreqInfo> { + // TODO: Get the correct frequency, use the local apic timer instead of the PIT. + let cpuid = CpuId::new(); + let hardcoded_frequency_in_hz = cpuid.get_tsc_info().map(|tsc| { + if tsc.numerator() != 0 { + // The core crystal clock frequency, in hertz. + Some(tsc.tsc_frequency()) + } else { None } + }).or_else(|| { + cpuid.get_processor_frequency_info().map(|freq| { + let bus_freq = freq.bus_frequency(); + if bus_freq != 0 { + Some(u64::from(bus_freq) * 1_000_000) + } else { None } + }) + }).flatten(); + + let frequency_in_hz = hardcoded_frequency_in_hz.unwrap_or_else(|| { + let (numer, denom) = self.determine_freq(); + let quotient = numer / denom; + quotient as u64 + }); + + let most_suitable_divider = most_suitable_divider(frequency_in_hz); + + println!("FREQUENCY: {}", frequency_in_hz); + println!("MOST_SUIT_DIV: {}", most_suitable_divider); + + let div_conf_value = most_suitable_divider; // divide by 128 + self.set_div_conf(div_conf_value.into()); let init_count_value = 1_000_000; self.set_init_count(init_count_value); @@ -204,12 +249,83 @@ impl LocalApic { let lvt_timer_value = ((LvtTimerMode::Periodic as u32) << 17) | 48u32; self.set_lvt_timer(lvt_timer_value); - // TODO: Get the correct frequency, use the local apic timer instead of the PIT. + Ok(()) + } + /// Determine the APIC timer frequency, if the info wasn't already retrieved directly from the + /// CPU. + unsafe fn determine_freq(&mut self) -> (u128, u128) { + let old_time = time::monotonic(); + let (old_time_s, old_time_ns) = old_time; + + super::super::idt::IDT[32].set_func(super::super::interrupt::irq::calib_pit); + + self.set_div_conf(0b1011); // divide by 1 + self.set_lvt_timer((LvtTimerMode::OneShot as u32) << 17 | 48); + + // enable both the apic timer and the pit timer simultaneously + interrupt::enable_and_nop(); + + self.set_init_count(0xFFFF_FFFF); + + let mut time; + + 'halt: loop { + time = time::monotonic(); + if time.0 > old_time_s || time.1 - old_time_ns > 10_000_000 { + break 'halt; + } + x86::halt(); + } + + let (time_s, time_ns) = time; + + let lvt_timer = self.lvt_timer(); + self.set_lvt_timer(lvt_timer | 1 << 16); + + let current_count = self.cur_count(); + + let lvt_timer_difference = 0xFFFF_FFFF - current_count; + let (s_difference, ns_difference) = (time_s - old_time_s, time_ns - old_time_ns); + + let freq_numer = u128::from(lvt_timer_difference) * 1_000_000_000; // multiply with a billion since we're dividing by nanoseconds. + let freq_denom_in_s = u128::from(s_difference) * 1_000_000_000 + u128::from(ns_difference); + + super::super::idt::IDT[32].set_func(super::super::interrupt::irq::pit); + + (freq_numer, freq_denom_in_s) } } + #[repr(u8)] pub enum LvtTimerMode { OneShot = 0b00, Periodic = 0b01, TscDeadline = 0b10, } + +/// Find the most suitable divider configuration value, which is useful if the reported frequency +/// is way too high to actually be useful. +fn most_suitable_divider(freq: u64) -> u8 { + // the current scheduler switches process about every 40 µs, with 4 µs per tick. + let quotient = (freq * 1000) / 2_000_000_000; + if quotient == 0 { + // the frequency is way to low, so the pit should be used + println!("Suboptimal APIC timer frequency"); + 0b1011 // divide by 1 + } else if quotient == 1 { + // the frequency closely matches the requested frequency, so use divider 1 + 0b1011 + } else if quotient < 4 { + 0b0000 // divider 2 + } else if quotient < 8 { + 0b0001 // divider 4 + } else if quotient < 16 { + 0b0010 // divider 8 + } else if quotient < 32 { + 0b0011 // divider 16 + } else if quotient < 64 { + 0b1001 // divider 64 + } else { + 0b1010 // divider 128 + } +} diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs index 7ca296d..662cf2f 100644 --- a/src/arch/x86_64/idt.rs +++ b/src/arch/x86_64/idt.rs @@ -1,10 +1,14 @@ use core::mem; +use core::num::NonZeroU8; + use x86::segmentation::Descriptor as X86IdtEntry; use x86::dtables::{self, DescriptorTablePointer}; use crate::interrupt::*; use crate::ipi::IpiKind; +use spin::Mutex; + pub static mut INIT_IDTR: DescriptorTablePointer = DescriptorTablePointer { limit: 0, base: 0 as *const X86IdtEntry @@ -15,7 +19,68 @@ pub static mut IDTR: DescriptorTablePointer = DescriptorTablePointe base: 0 as *const X86IdtEntry }; +// TODO: It's probably a good idea to use a separate IDT (and IDT_RESERVATIONS) for each CPU. +// Currently 202 interrupts are freely allocatable, for the IDT, but if different CPUs received +// different IDTs, the number would go up to e.g. 1616 IRQs on a processor with 8 logical CPUs. + pub static mut IDT: [IdtEntry; 256] = [IdtEntry::new(); 256]; +pub static IDT_RESERVATIONS: Mutex<[u64; 256 / 64]> = Mutex::new([0u64; 256 / 64]); + +#[inline] +pub fn is_reserved(index: u8) -> bool { + let byte_index = index / 64; + let bit = index % 64; + + IDT_RESERVATIONS.lock()[usize::from(byte_index)] & (1 << bit) != 0 +} + +#[inline] +pub fn set_reserved(index: u8, reserved: bool) { + let byte_index = index / 64; + let bit = index % 64; + + IDT_RESERVATIONS.lock()[usize::from(byte_index)] |= u64::from(reserved) << bit; +} + +pub fn allocate_interrupt() -> Option { + for number in 50..=255 { + if ! is_reserved(number) { + set_reserved(number, true); + return Some(unsafe { NonZeroU8::new_unchecked(number) }); + } + } + None +} + +pub fn available_irqs_iter() -> impl Iterator + 'static { + AvailableIrqsIter { index: Some(50) }.filter(|&index| !is_reserved(index)) +} + +struct AvailableIrqsIter { + index: Option, +} +impl Iterator for AvailableIrqsIter { + type Item = u8; + + fn next(&mut self) -> Option { + let index = self.index?; + self.index = index.checked_add(1); + Some(index) + } +} + +macro_rules! use_irq( + ( $number:literal, $func:ident ) => { + IDT[$number].set_func($func); + } +); + +macro_rules! use_default_irqs( + () => {{ + use crate::interrupt::irq::*; + default_irqs!(use_irq); + }} +); pub unsafe fn init() { dtables::lidt(&INIT_IDTR); @@ -52,6 +117,9 @@ pub unsafe fn init_paging() { IDT[30].set_func(exception::security); // 31 reserved + // reserve bits 31:0, i.e. the first 32 interrupts, which are reserved for exceptions + IDT_RESERVATIONS.lock()[0] |= 0x0000_0000_FFFF_FFFF; + // Set up IRQs IDT[32].set_func(irq::pit); IDT[33].set_func(irq::keyboard); @@ -72,15 +140,25 @@ pub unsafe fn init_paging() { IDT[48].set_func(irq::lapic_timer); IDT[49].set_func(irq::lapic_error); + use_default_irqs!(); + + // reserve bits 49:32, which are for the standard IRQs, and for the local apic timer and error. + IDT_RESERVATIONS.lock()[0] |= 0x0003_FFFF_0000_0000; + // Set IPI handlers IDT[IpiKind::Wakeup as usize].set_func(ipi::wakeup); IDT[IpiKind::Switch as usize].set_func(ipi::switch); IDT[IpiKind::Tlb as usize].set_func(ipi::tlb); IDT[IpiKind::Pit as usize].set_func(ipi::pit); + set_reserved(IpiKind::Wakeup as u8, true); + set_reserved(IpiKind::Switch as u8, true); + set_reserved(IpiKind::Tlb as u8, true); + set_reserved(IpiKind::Pit as u8, true); // Set syscall function IDT[0x80].set_func(syscall::syscall); IDT[0x80].set_flags(IdtFlags::PRESENT | IdtFlags::RING_3 | IdtFlags::INTERRUPT); + set_reserved(0x80, true); dtables::lidt(&IDTR); } diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs index 632cd4f..637f55a 100644 --- a/src/arch/x86_64/interrupt/irq.rs +++ b/src/arch/x86_64/interrupt/irq.rs @@ -143,3 +143,36 @@ interrupt!(lapic_error, { println!("Local apic internal error: ESR={:#0x}", local_apic::LOCAL_APIC.esr()); lapic_eoi(); }); +interrupt!(msi_vector, { + println!("MSI interrupt"); + lapic_eoi(); +}); +interrupt!(calib_pit, { + const PIT_RATE: u64 = 2_250_286; + + { + let mut offset = time::OFFSET.lock(); + let sum = offset.1 + PIT_RATE; + offset.1 = sum % 1_000_000_000; + offset.0 += sum / 1_000_000_000; + } + + pic::MASTER.ack(); +}); +// XXX: This would look way prettier using const generics. + +macro_rules! allocatable_irq( + ( $number:literal, $name:ident ) => { + interrupt!($name, { + allocatable_irq_generic($number); + }); + } +); + +pub unsafe fn allocatable_irq_generic(number: u8) { + println!("generic irq: {}", number); + trigger(number - 32); + lapic_eoi(); // not sure if needed +} + +define_default_irqs!(); diff --git a/src/arch/x86_64/interrupt/mod.rs b/src/arch/x86_64/interrupt/mod.rs index 85686d9..fcf75d1 100644 --- a/src/arch/x86_64/interrupt/mod.rs +++ b/src/arch/x86_64/interrupt/mod.rs @@ -8,6 +8,9 @@ pub mod trace; pub use self::trace::stack_trace; +pub use super::idt::{available_irqs_iter, is_reserved, set_reserved}; +pub use super::device::local_apic::bsp_apic_id; + /// Clear interrupts #[inline(always)] pub unsafe fn disable() { diff --git a/src/arch/x86_64/macros.rs b/src/arch/x86_64/macros.rs index dbbd424..d3d50b6 100644 --- a/src/arch/x86_64/macros.rs +++ b/src/arch/x86_64/macros.rs @@ -392,3 +392,55 @@ macro_rules! interrupt_error { } }; } +#[macro_export] +macro_rules! irqs( + ( [ $( ($number:literal, $name:ident) ,)* ], $submac:ident ) => { + $( + $submac!($number, $name); + )* + } +); + +// define the irq numbers specified in the list above, as functions of the names +// allocatable_irq_NUM. +#[macro_export] +macro_rules! default_irqs( + ($submac:ident) => { + irqs!([ + // interrupt vectors below 32 are exceptions + // vectors 32..=47 are used for standard 8259 pic irqs. + // 48 and 49 are used for the local APIC timer and error register, respectively. + (50, irq_50), (51, irq_51), (52, irq_52), (53, irq_53), (54, irq_54), (55, irq_55), (56, irq_56), (57, irq_57), (58, irq_58), (59, irq_59), + (60, irq_60), (61, irq_61), (62, irq_62), (63, irq_63), + // 64..=67 used for IPI + (68, irq_68), (69, irq_69), + (70, irq_70), (71, irq_71), (72, irq_72), (73, irq_73), (74, irq_74), (75, irq_75), (76, irq_76), (77, irq_77), (78, irq_78), (79, irq_79), + (80, irq_80), (81, irq_81), (82, irq_82), (83, irq_83), (84, irq_84), (85, irq_85), (86, irq_86), (87, irq_87), (88, irq_88), (89, irq_89), + (90, irq_90), (91, irq_91), (92, irq_92), (93, irq_93), (94, irq_94), (95, irq_95), (96, irq_96), (97, irq_97), (98, irq_98), (99, irq_99), + (100, irq_100), (101, irq_101), (102, irq_102), (103, irq_103), (104, irq_104), (105, irq_105), (106, irq_106), (107, irq_107), (108, irq_108), (109, irq_109), + (110, irq_110), (111, irq_111), (112, irq_112), (113, irq_113), (114, irq_114), (115, irq_115), (116, irq_116), (117, irq_117), (118, irq_118), (119, irq_119), + (120, irq_120), (121, irq_121), (122, irq_122), (123, irq_123), (124, irq_124), (125, irq_125), (126, irq_126), (127, irq_127), + // 128 is used for software interrupts + (129, irq_129), + (130, irq_130), (131, irq_131), (132, irq_132), (133, irq_133), (134, irq_134), (135, irq_135), (136, irq_136), (137, irq_137), (138, irq_138), (139, irq_139), + (140, irq_140), (141, irq_141), (142, irq_142), (143, irq_143), (144, irq_144), (145, irq_145), (146, irq_146), (147, irq_147), (148, irq_148), (149, irq_149), + (150, irq_150), (151, irq_151), (152, irq_152), (153, irq_153), (154, irq_154), (155, irq_155), (156, irq_156), (157, irq_157), (158, irq_158), (159, irq_159), + (160, irq_160), (161, irq_161), (162, irq_162), (163, irq_163), (164, irq_164), (165, irq_165), (166, irq_166), (167, irq_167), (168, irq_168), (169, irq_169), + (170, irq_170), (171, irq_171), (172, irq_172), (173, irq_173), (174, irq_174), (175, irq_175), (176, irq_176), (177, irq_177), (178, irq_178), (179, irq_179), + (180, irq_180), (181, irq_181), (182, irq_182), (183, irq_183), (184, irq_184), (185, irq_185), (186, irq_186), (187, irq_187), (188, irq_188), (189, irq_189), + (190, irq_190), (191, irq_191), (192, irq_192), (193, irq_193), (194, irq_194), (195, irq_195), (196, irq_196), (197, irq_197), (198, irq_198), (199, irq_199), + (200, irq_200), (201, irq_201), (202, irq_202), (203, irq_203), (204, irq_204), (205, irq_205), (206, irq_206), (207, irq_207), (208, irq_208), (209, irq_209), + (210, irq_210), (211, irq_211), (212, irq_212), (213, irq_213), (214, irq_214), (215, irq_215), (216, irq_216), (217, irq_217), (218, irq_218), (219, irq_219), + (220, irq_220), (221, irq_221), (222, irq_222), (223, irq_223), (224, irq_224), (225, irq_225), (226, irq_226), (227, irq_227), (228, irq_228), (229, irq_229), + (230, irq_230), (231, irq_231), (232, irq_232), (233, irq_233), (234, irq_234), (235, irq_235), (236, irq_236), (237, irq_237), (238, irq_238), (239, irq_239), + (240, irq_240), (241, irq_241), (242, irq_242), (243, irq_243), (244, irq_244), (245, irq_245), (246, irq_246), (247, irq_247), (248, irq_248), (249, irq_249), + (250, irq_250), (251, irq_251), (252, irq_252), (253, irq_253), (254, irq_254), (255, irq_255), + ], $submac); + } +); + +macro_rules! define_default_irqs( + () => { + default_irqs!(allocatable_irq); + } +); diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 715bcad..6468893 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -14,12 +14,13 @@ pub mod gdt; #[cfg(feature = "graphical_debug")] mod graphical_debug; +/// Interrupt instructions +#[macro_use] +pub mod interrupt; + /// Interrupt descriptor table pub mod idt; -/// Interrupt instructions -pub mod interrupt; - /// Inter-processor interrupts pub mod ipi; diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index a238698..18ee836 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -3,20 +3,39 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use spin::{Mutex, RwLock}; use alloc::collections::BTreeMap; +use alloc::vec::Vec; +use alloc::string::String; + +use crate::arch::interrupt::{available_irqs_iter, bsp_apic_id, is_reserved, set_reserved}; use crate::event; use crate::interrupt::irq::acknowledge; use crate::scheme::{AtomicSchemeId, SchemeId}; use crate::syscall::error::*; -use crate::syscall::flag::{EventFlags, EVENT_READ}; +use crate::syscall::flag::{EventFlags, EVENT_READ, O_DIRECTORY, O_CREAT, O_STAT, MODE_CHR, MODE_DIR, SEEK_CUR, SEEK_END, SEEK_SET}; use crate::syscall::scheme::Scheme; pub static IRQ_SCHEME_ID: AtomicSchemeId = AtomicSchemeId::default(); /// IRQ queues -static COUNTS: Mutex<[usize; 16]> = Mutex::new([0; 16]); +static COUNTS: Mutex<[usize; 224]> = Mutex::new([0; 224]); static HANDLES: RwLock>> = RwLock::new(None); +/// These are IRQs 0..=15 (corresponding to interrupt vectors 32..=47). They are opened without the +/// O_CREAT flag. +const BASE_IRQ_COUNT: u8 = 16; + +/// These are the extended IRQs, 16..=223 (interrupt vectors 48..=255). Some of them are reserved +/// for other devices, and some other interrupt vectors like 0x80 (software interrupts) and +/// 0x40..=0x43 (IPI). +/// +/// Since these are non-sharable, they must be opened with O_CREAT, which then reserves them. They +/// are only freed when the file descriptor is closed. +const TOTAL_IRQ_COUNT: u8 = 224; + +const INO_AVAIL: u64 = 0x8000_0000_0000_0000; +const INO_BSP: u64 = 0x8000_0000_0000_0001; + /// Add to the input queue #[no_mangle] pub extern fn irq_trigger(irq: u8) { @@ -24,7 +43,7 @@ pub extern fn irq_trigger(irq: u8) { let guard = HANDLES.read(); if let Some(handles) = guard.as_ref() { - for (fd, _) in handles.iter().filter(|(_, handle)| handle.irq == irq) { + for (fd, _) in handles.iter().filter_map(|(fd, handle)| Some((fd, handle.as_irq_handle()?))).filter(|&(_, (_, handle_irq))| handle_irq == irq) { event::trigger(IRQ_SCHEME_ID.load(Ordering::SeqCst), *fd, EVENT_READ); } } else { @@ -32,9 +51,21 @@ pub extern fn irq_trigger(irq: u8) { } } -struct Handle { - ack: AtomicUsize, - irq: u8, +enum Handle { + Irq { + ack: AtomicUsize, + irq: u8, + }, + Avail(Vec, AtomicUsize), + Bsp, +} +impl Handle { + fn as_irq_handle<'a>(&'a self) -> Option<(&'a AtomicUsize, u8)> { + match self { + &Self::Irq { ref ack, irq } => Some((ack, irq)), + _ => None, + } + } } pub struct IrqScheme { @@ -53,67 +84,185 @@ impl IrqScheme { } } +const fn irq_to_vector(irq: u8) -> u8 { + irq + 32 +} +const fn vector_to_irq(vector: u8) -> u8 { + vector - 32 +} + impl Scheme for IrqScheme { - fn open(&self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result { - if uid == 0 { - let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; + fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { + if uid != 0 { return Err(Error::new(EACCES)) } - let id = path_str.parse::().or(Err(Error::new(ENOENT)))?; + let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; + let path_str = path_str.trim_start_matches('/'); - if id < COUNTS.lock().len() { - let fd = self.next_fd.fetch_add(1, Ordering::Relaxed); - HANDLES.write().as_mut().unwrap().insert(fd, Handle { ack: AtomicUsize::new(0), irq: id as u8 }); - Ok(fd) - } else { - Err(Error::new(ENOENT)) + let handle = if (flags & O_DIRECTORY != 0 || flags & O_STAT != 0) && path_str.is_empty() { + // list all of the allocatable IRQs + + let mut bytes = String::new(); + + use core::fmt::Write; + + for avail in available_irqs_iter() { + write!(bytes, "{}\n", vector_to_irq(avail)).unwrap(); } + if bsp_apic_id().is_some() { + write!(bytes, "bsp\n").unwrap(); + } + + Handle::Avail(bytes.into_bytes(), AtomicUsize::new(0)) } else { - Err(Error::new(EACCES)) - } + if path_str == "bsp" { + if bsp_apic_id().is_none() { + return Err(Error::new(ENOENT)); + } + Handle::Bsp + } else if let Ok(id) = path_str.parse::() { + if id < BASE_IRQ_COUNT { + Handle::Irq { ack: AtomicUsize::new(0), irq: id } + } else if id < TOTAL_IRQ_COUNT { + if flags & O_CREAT == 0 && flags & O_STAT == 0 { + return Err(Error::new(EINVAL)); + } + if flags & O_STAT == 0 { + + if is_reserved(irq_to_vector(id)) { + return Err(Error::new(EEXIST)); + } + set_reserved(irq_to_vector(id), true); + } + Handle::Irq { ack: AtomicUsize::new(0), irq: id } + } else { + return Err(Error::new(ENOENT)); + } + } else { + return Err(Error::new(ENOENT)); + } + }; + let fd = self.next_fd.fetch_add(1, Ordering::SeqCst); + HANDLES.write().as_mut().unwrap().insert(fd, handle); + Ok(fd) } fn read(&self, file: usize, buffer: &mut [u8]) -> Result { - // Ensures that the length of the buffer is larger than the size of a usize - if buffer.len() >= mem::size_of::() { - let handles_guard = HANDLES.read(); - let handle = &handles_guard.as_ref().unwrap().get(&file).ok_or(Error::new(EBADF))?; + let handles_guard = HANDLES.read(); + let handle = handles_guard.as_ref().unwrap().get(&file).ok_or(Error::new(EBADF))?; - let current = COUNTS.lock()[handle.irq as usize]; - if handle.ack.load(Ordering::SeqCst) != current { - // Safe if the length of the buffer is larger than the size of a usize - assert!(buffer.len() >= mem::size_of::()); - unsafe { *(buffer.as_mut_ptr() as *mut usize) = current; } - Ok(mem::size_of::()) + match handle { + // Ensures that the length of the buffer is larger than the size of a usize + &Handle::Irq { irq: handle_irq, ack: ref handle_ack } => if buffer.len() >= mem::size_of::() { + let current = COUNTS.lock()[handle_irq as usize]; + if handle_ack.load(Ordering::SeqCst) != current { + // Safe if the length of the buffer is larger than the size of a usize + assert!(buffer.len() >= mem::size_of::()); + unsafe { *(buffer.as_mut_ptr() as *mut usize) = current; } + Ok(mem::size_of::()) + } else { + Ok(0) + } } else { - Ok(0) + return Err(Error::new(EINVAL)); } - } else { - Err(Error::new(EINVAL)) + &Handle::Bsp => { + if buffer.len() < mem::size_of::() { + return Err(Error::new(EINVAL)); + } + if let Some(bsp_apic_id) = bsp_apic_id() { + unsafe { *(buffer.as_mut_ptr() as *mut usize) = bsp_apic_id as usize; } + Ok(mem::size_of::()) + } else { + return Err(Error::new(EBADFD)); + } + } + &Handle::Avail(ref buf, ref offset) => { + let cur_offset = offset.load(Ordering::SeqCst); + let max_bytes_to_read = core::cmp::min(buf.len(), buffer.len()); + let bytes_to_read = core::cmp::max(max_bytes_to_read, cur_offset) - cur_offset; + buffer[..bytes_to_read].copy_from_slice(&buf[cur_offset..cur_offset + bytes_to_read]); + offset.fetch_add(bytes_to_read, Ordering::SeqCst); + Ok(bytes_to_read) + } + } + } + + fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { + let handles_guard = HANDLES.read(); + let handle = handles_guard.as_ref().unwrap().get(&id).ok_or(Error::new(EBADF))?; + + match handle { + &Handle::Avail(ref buf, ref offset) => { + let cur_offset = offset.load(Ordering::SeqCst); + let new_offset = match whence { + SEEK_CUR => core::cmp::min(cur_offset + pos, buf.len()), + SEEK_END => core::cmp::min(buf.len() + pos, buf.len()), + SEEK_SET => core::cmp::min(buf.len(), pos), + _ => return Err(Error::new(EINVAL)), + }; + offset.store(new_offset, Ordering::SeqCst); + Ok(new_offset) + } + _ => return Err(Error::new(ESPIPE)), } } fn write(&self, file: usize, buffer: &[u8]) -> Result { - if buffer.len() >= mem::size_of::() { - assert!(buffer.len() >= mem::size_of::()); + let handles_guard = HANDLES.read(); + let handle = handles_guard.as_ref().unwrap().get(&file).ok_or(Error::new(EBADF))?; - let handles_guard = HANDLES.read(); - let handle = &handles_guard.as_ref().unwrap().get(&file).ok_or(Error::new(EBADF))?; + match handle { + &Handle::Irq { irq: handle_irq, ack: ref handle_ack } => if buffer.len() >= mem::size_of::() { + assert!(buffer.len() >= mem::size_of::()); - let ack = unsafe { *(buffer.as_ptr() as *const usize) }; - let current = COUNTS.lock()[handle.irq as usize]; + let ack = unsafe { *(buffer.as_ptr() as *const usize) }; + let current = COUNTS.lock()[handle_irq as usize]; - if ack == current { - handle.ack.store(ack, Ordering::SeqCst); - unsafe { acknowledge(handle.irq as usize); } - Ok(mem::size_of::()) + if ack == current { + handle_ack.store(ack, Ordering::SeqCst); + unsafe { acknowledge(handle_irq as usize); } + Ok(mem::size_of::()) + } else { + Ok(0) + } } else { - Ok(0) + return Err(Error::new(EINVAL)); } - } else { - Err(Error::new(EINVAL)) + _ => return Err(Error::new(EBADF)), } } + fn fstat(&self, id: usize, stat: &mut syscall::data::Stat) -> Result { + let handles_guard = HANDLES.read(); + let handle = handles_guard.as_ref().unwrap().get(&id).ok_or(Error::new(EBADF))?; + + match handle { + &Handle::Irq { irq: handle_irq, .. } => { + stat.st_mode = MODE_CHR | 0o600; + stat.st_size = mem::size_of::() as u64; + stat.st_blocks = 1; + stat.st_blksize = mem::size_of::() as u32; + stat.st_ino = handle_irq.into(); + stat.st_nlink = 1; + } + Handle::Bsp => { + stat.st_mode = MODE_CHR | 0o400; + stat.st_size = mem::size_of::() as u64; + stat.st_blocks = 1; + stat.st_blksize = mem::size_of::() as u32; + stat.st_ino = INO_BSP; + stat.st_nlink = 1; + } + Handle::Avail(ref buf, _) => { + stat.st_mode = MODE_DIR | 0o500; + stat.st_size = buf.len() as u64; + stat.st_ino = INO_AVAIL; + stat.st_nlink = 2; + } + } + Ok(0) + } + fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result { Ok(0) } @@ -123,8 +272,15 @@ impl Scheme for IrqScheme { } fn fpath(&self, id: usize, buf: &mut [u8]) -> Result { + let handles_guard = HANDLES.read(); + let handle = handles_guard.as_ref().unwrap().get(&id).ok_or(Error::new(EBADF))?; + + let scheme_path = match handle { + &Handle::Irq { irq, .. } => format!("irq:{}", irq), + &Handle::Bsp => format!("irq:bsp"), + &Handle::Avail(_, _) => format!("irq:"), + }.into_bytes(); let mut i = 0; - let scheme_path = format!("irq:{}", id).into_bytes(); while i < buf.len() && i < scheme_path.len() { buf[i] = scheme_path[i]; i += 1; @@ -136,7 +292,15 @@ impl Scheme for IrqScheme { Ok(0) } - fn close(&self, _file: usize) -> Result { + fn close(&self, id: usize) -> Result { + let handles_guard = HANDLES.read(); + let handle = handles_guard.as_ref().unwrap().get(&id).ok_or(Error::new(EBADF))?; + + if let &Handle::Irq { irq: handle_irq, .. } = handle { + if handle_irq > BASE_IRQ_COUNT { + set_reserved(irq_to_vector(handle_irq), false); + } + } Ok(0) } } From 157a3e5c0d7ecfa6e63a052b6dbcb098c190ce7a Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 27 Mar 2020 16:21:15 +0100 Subject: [PATCH 5/8] Improve MSI. --- src/arch/x86_64/device/local_apic.rs | 205 +++++++++++++++++++++++++++ src/arch/x86_64/interrupt/irq.rs | 15 +- src/scheme/irq.rs | 2 +- 3 files changed, 212 insertions(+), 10 deletions(-) diff --git a/src/arch/x86_64/device/local_apic.rs b/src/arch/x86_64/device/local_apic.rs index 03565cf..895a55b 100644 --- a/src/arch/x86_64/device/local_apic.rs +++ b/src/arch/x86_64/device/local_apic.rs @@ -251,6 +251,211 @@ impl LocalApic { Ok(()) } + pub unsafe fn isr_bits_31_0(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_ISR0) as u32 + } else { + self.read(0x100) + } + } + pub unsafe fn isr_bits_63_32(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_ISR1) as u32 + } else { + self.read(0x110) + } + } + pub unsafe fn isr_bits_95_64(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_ISR2) as u32 + } else { + self.read(0x120) + } + } + pub unsafe fn isr_bits_127_96(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_ISR3) as u32 + } else { + self.read(0x130) + } + } + pub unsafe fn isr_bits_159_128(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_ISR4) as u32 + } else { + self.read(0x140) + } + } + pub unsafe fn isr_bits_191_160(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_ISR5) as u32 + } else { + self.read(0x150) + } + } + pub unsafe fn isr_bits_223_192(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_ISR6) as u32 + } else { + self.read(0x160) + } + } + pub unsafe fn isr_bits_255_224(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_ISR7) as u32 + } else { + self.read(0x170) + } + } + pub unsafe fn entire_isr(&mut self) -> [u32; 8] { + [ + self.isr_bits_31_0(), + self.isr_bits_63_32(), + self.isr_bits_95_64(), + self.isr_bits_127_96(), + self.isr_bits_159_128(), + self.isr_bits_191_160(), + self.isr_bits_223_192(), + self.isr_bits_255_224(), + ] + } + pub unsafe fn tmr_bits_31_0(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_TMR0) as u32 + } else { + self.read(0x180) + } + } + pub unsafe fn tmr_bits_63_32(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_TMR1) as u32 + } else { + self.read(0x190) + } + } + pub unsafe fn tmr_bits_95_64(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_TMR2) as u32 + } else { + self.read(0x1A0) + } + } + pub unsafe fn tmr_bits_127_96(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_TMR3) as u32 + } else { + self.read(0x1B0) + } + } + pub unsafe fn tmr_bits_159_128(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_TMR4) as u32 + } else { + self.read(0x1C0) + } + } + pub unsafe fn tmr_bits_191_160(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_TMR5) as u32 + } else { + self.read(0x1D0) + } + } + pub unsafe fn tmr_bits_223_192(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_TMR6) as u32 + } else { + self.read(0x1E0) + } + } + pub unsafe fn tmr_bits_255_224(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_TMR7) as u32 + } else { + self.read(0x1F0) + } + } + pub unsafe fn entire_tmr(&mut self) -> [u32; 8] { + [ + self.tmr_bits_31_0(), + self.tmr_bits_63_32(), + self.tmr_bits_95_64(), + self.tmr_bits_127_96(), + self.tmr_bits_159_128(), + self.tmr_bits_191_160(), + self.tmr_bits_223_192(), + self.tmr_bits_255_224(), + ] + } + pub unsafe fn irr_bits_31_0(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_IRR0) as u32 + } else { + self.read(0x200) + } + } + pub unsafe fn irr_bits_63_32(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_IRR1) as u32 + } else { + self.read(0x210) + } + } + pub unsafe fn irr_bits_95_64(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_IRR2) as u32 + } else { + self.read(0x220) + } + } + pub unsafe fn irr_bits_127_96(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_IRR3) as u32 + } else { + self.read(0x230) + } + } + pub unsafe fn irr_bits_159_128(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_IRR4) as u32 + } else { + self.read(0x240) + } + } + pub unsafe fn irr_bits_191_160(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_IRR5) as u32 + } else { + self.read(0x250) + } + } + pub unsafe fn irr_bits_223_192(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_IRR6) as u32 + } else { + self.read(0x260) + } + } + pub unsafe fn irr_bits_255_224(&mut self) -> u32 { + if self.x2 { + rdmsr(IA32_X2APIC_IRR7) as u32 + } else { + self.read(0x270) + } + } + pub unsafe fn entire_irr(&mut self) -> [u32; 8] { + [ + self.irr_bits_31_0(), + self.irr_bits_63_32(), + self.irr_bits_95_64(), + self.irr_bits_127_96(), + self.irr_bits_159_128(), + self.irr_bits_191_160(), + self.irr_bits_223_192(), + self.irr_bits_255_224(), + ] + } + /// Determine the APIC timer frequency, if the info wasn't already retrieved directly from the /// CPU. unsafe fn determine_freq(&mut self) -> (u128, u128) { diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs index 637f55a..4d8f86c 100644 --- a/src/arch/x86_64/interrupt/irq.rs +++ b/src/arch/x86_64/interrupt/irq.rs @@ -11,10 +11,11 @@ use crate::{context, ptrace, time}; #[thread_local] pub static PIT_TICKS: AtomicUsize = AtomicUsize::new(0); +extern { + fn irq_trigger(irq: u8); +} + unsafe fn trigger(irq: u8) { - extern { - fn irq_trigger(irq: u8); - } if irq < 16 { if irq >= 8 { @@ -143,10 +144,6 @@ interrupt!(lapic_error, { println!("Local apic internal error: ESR={:#0x}", local_apic::LOCAL_APIC.esr()); lapic_eoi(); }); -interrupt!(msi_vector, { - println!("MSI interrupt"); - lapic_eoi(); -}); interrupt!(calib_pit, { const PIT_RATE: u64 = 2_250_286; @@ -171,8 +168,8 @@ macro_rules! allocatable_irq( pub unsafe fn allocatable_irq_generic(number: u8) { println!("generic irq: {}", number); - trigger(number - 32); - lapic_eoi(); // not sure if needed + irq_trigger(number - 32); + lapic_eoi(); } define_default_irqs!(); diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index 18ee836..b3784e6 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -43,7 +43,7 @@ pub extern fn irq_trigger(irq: u8) { let guard = HANDLES.read(); if let Some(handles) = guard.as_ref() { - for (fd, _) in handles.iter().filter_map(|(fd, handle)| Some((fd, handle.as_irq_handle()?))).filter(|&(_, (_, handle_irq))| handle_irq == irq) { + for (fd, (_, handle_irq)) in handles.iter().filter_map(|(fd, handle)| Some((fd, handle.as_irq_handle()?))).filter(|&(_, (_, handle_irq))| handle_irq == irq) { event::trigger(IRQ_SCHEME_ID.load(Ordering::SeqCst), *fd, EVENT_READ); } } else { From d23ed0cfc34c9155af8d129a774bcbdfc5e9d830 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 28 Mar 2020 12:35:18 +0100 Subject: [PATCH 6/8] Remove debug local APIC functions. --- src/arch/x86_64/device/local_apic.rs | 204 --------------------------- 1 file changed, 204 deletions(-) diff --git a/src/arch/x86_64/device/local_apic.rs b/src/arch/x86_64/device/local_apic.rs index 895a55b..38a8e1c 100644 --- a/src/arch/x86_64/device/local_apic.rs +++ b/src/arch/x86_64/device/local_apic.rs @@ -251,210 +251,6 @@ impl LocalApic { Ok(()) } - pub unsafe fn isr_bits_31_0(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_ISR0) as u32 - } else { - self.read(0x100) - } - } - pub unsafe fn isr_bits_63_32(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_ISR1) as u32 - } else { - self.read(0x110) - } - } - pub unsafe fn isr_bits_95_64(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_ISR2) as u32 - } else { - self.read(0x120) - } - } - pub unsafe fn isr_bits_127_96(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_ISR3) as u32 - } else { - self.read(0x130) - } - } - pub unsafe fn isr_bits_159_128(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_ISR4) as u32 - } else { - self.read(0x140) - } - } - pub unsafe fn isr_bits_191_160(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_ISR5) as u32 - } else { - self.read(0x150) - } - } - pub unsafe fn isr_bits_223_192(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_ISR6) as u32 - } else { - self.read(0x160) - } - } - pub unsafe fn isr_bits_255_224(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_ISR7) as u32 - } else { - self.read(0x170) - } - } - pub unsafe fn entire_isr(&mut self) -> [u32; 8] { - [ - self.isr_bits_31_0(), - self.isr_bits_63_32(), - self.isr_bits_95_64(), - self.isr_bits_127_96(), - self.isr_bits_159_128(), - self.isr_bits_191_160(), - self.isr_bits_223_192(), - self.isr_bits_255_224(), - ] - } - pub unsafe fn tmr_bits_31_0(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_TMR0) as u32 - } else { - self.read(0x180) - } - } - pub unsafe fn tmr_bits_63_32(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_TMR1) as u32 - } else { - self.read(0x190) - } - } - pub unsafe fn tmr_bits_95_64(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_TMR2) as u32 - } else { - self.read(0x1A0) - } - } - pub unsafe fn tmr_bits_127_96(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_TMR3) as u32 - } else { - self.read(0x1B0) - } - } - pub unsafe fn tmr_bits_159_128(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_TMR4) as u32 - } else { - self.read(0x1C0) - } - } - pub unsafe fn tmr_bits_191_160(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_TMR5) as u32 - } else { - self.read(0x1D0) - } - } - pub unsafe fn tmr_bits_223_192(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_TMR6) as u32 - } else { - self.read(0x1E0) - } - } - pub unsafe fn tmr_bits_255_224(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_TMR7) as u32 - } else { - self.read(0x1F0) - } - } - pub unsafe fn entire_tmr(&mut self) -> [u32; 8] { - [ - self.tmr_bits_31_0(), - self.tmr_bits_63_32(), - self.tmr_bits_95_64(), - self.tmr_bits_127_96(), - self.tmr_bits_159_128(), - self.tmr_bits_191_160(), - self.tmr_bits_223_192(), - self.tmr_bits_255_224(), - ] - } - pub unsafe fn irr_bits_31_0(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_IRR0) as u32 - } else { - self.read(0x200) - } - } - pub unsafe fn irr_bits_63_32(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_IRR1) as u32 - } else { - self.read(0x210) - } - } - pub unsafe fn irr_bits_95_64(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_IRR2) as u32 - } else { - self.read(0x220) - } - } - pub unsafe fn irr_bits_127_96(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_IRR3) as u32 - } else { - self.read(0x230) - } - } - pub unsafe fn irr_bits_159_128(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_IRR4) as u32 - } else { - self.read(0x240) - } - } - pub unsafe fn irr_bits_191_160(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_IRR5) as u32 - } else { - self.read(0x250) - } - } - pub unsafe fn irr_bits_223_192(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_IRR6) as u32 - } else { - self.read(0x260) - } - } - pub unsafe fn irr_bits_255_224(&mut self) -> u32 { - if self.x2 { - rdmsr(IA32_X2APIC_IRR7) as u32 - } else { - self.read(0x270) - } - } - pub unsafe fn entire_irr(&mut self) -> [u32; 8] { - [ - self.irr_bits_31_0(), - self.irr_bits_63_32(), - self.irr_bits_95_64(), - self.irr_bits_127_96(), - self.irr_bits_159_128(), - self.irr_bits_191_160(), - self.irr_bits_223_192(), - self.irr_bits_255_224(), - ] - } /// Determine the APIC timer frequency, if the info wasn't already retrieved directly from the /// CPU. From b716ec4bc1631fa830f788a747ed4f17485b3d48 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 28 Mar 2020 12:37:38 +0100 Subject: [PATCH 7/8] Remove currently unused APIC timer code. --- src/arch/x86_64/device/local_apic.rs | 111 --------------------------- src/scheme/irq.rs | 2 +- 2 files changed, 1 insertion(+), 112 deletions(-) diff --git a/src/arch/x86_64/device/local_apic.rs b/src/arch/x86_64/device/local_apic.rs index 38a8e1c..e878c12 100644 --- a/src/arch/x86_64/device/local_apic.rs +++ b/src/arch/x86_64/device/local_apic.rs @@ -6,7 +6,6 @@ use x86::msr::*; use crate::memory::Frame; use crate::paging::{ActivePageTable, PhysicalAddress, Page, VirtualAddress}; use crate::paging::entry::EntryFlags; -use crate::{interrupt, time}; pub static mut LOCAL_APIC: LocalApic = LocalApic { address: 0, @@ -212,89 +211,6 @@ impl LocalApic { let vector = 49u32; self.set_lvt_error(vector); } - unsafe fn setup_timer(&mut self) -> Result<(), NoFreqInfo> { - // TODO: Get the correct frequency, use the local apic timer instead of the PIT. - let cpuid = CpuId::new(); - let hardcoded_frequency_in_hz = cpuid.get_tsc_info().map(|tsc| { - if tsc.numerator() != 0 { - // The core crystal clock frequency, in hertz. - Some(tsc.tsc_frequency()) - } else { None } - }).or_else(|| { - cpuid.get_processor_frequency_info().map(|freq| { - let bus_freq = freq.bus_frequency(); - if bus_freq != 0 { - Some(u64::from(bus_freq) * 1_000_000) - } else { None } - }) - }).flatten(); - - let frequency_in_hz = hardcoded_frequency_in_hz.unwrap_or_else(|| { - let (numer, denom) = self.determine_freq(); - let quotient = numer / denom; - quotient as u64 - }); - - let most_suitable_divider = most_suitable_divider(frequency_in_hz); - - println!("FREQUENCY: {}", frequency_in_hz); - println!("MOST_SUIT_DIV: {}", most_suitable_divider); - - let div_conf_value = most_suitable_divider; // divide by 128 - self.set_div_conf(div_conf_value.into()); - - let init_count_value = 1_000_000; - self.set_init_count(init_count_value); - - let lvt_timer_value = ((LvtTimerMode::Periodic as u32) << 17) | 48u32; - self.set_lvt_timer(lvt_timer_value); - - Ok(()) - } - - /// Determine the APIC timer frequency, if the info wasn't already retrieved directly from the - /// CPU. - unsafe fn determine_freq(&mut self) -> (u128, u128) { - let old_time = time::monotonic(); - let (old_time_s, old_time_ns) = old_time; - - super::super::idt::IDT[32].set_func(super::super::interrupt::irq::calib_pit); - - self.set_div_conf(0b1011); // divide by 1 - self.set_lvt_timer((LvtTimerMode::OneShot as u32) << 17 | 48); - - // enable both the apic timer and the pit timer simultaneously - interrupt::enable_and_nop(); - - self.set_init_count(0xFFFF_FFFF); - - let mut time; - - 'halt: loop { - time = time::monotonic(); - if time.0 > old_time_s || time.1 - old_time_ns > 10_000_000 { - break 'halt; - } - x86::halt(); - } - - let (time_s, time_ns) = time; - - let lvt_timer = self.lvt_timer(); - self.set_lvt_timer(lvt_timer | 1 << 16); - - let current_count = self.cur_count(); - - let lvt_timer_difference = 0xFFFF_FFFF - current_count; - let (s_difference, ns_difference) = (time_s - old_time_s, time_ns - old_time_ns); - - let freq_numer = u128::from(lvt_timer_difference) * 1_000_000_000; // multiply with a billion since we're dividing by nanoseconds. - let freq_denom_in_s = u128::from(s_difference) * 1_000_000_000 + u128::from(ns_difference); - - super::super::idt::IDT[32].set_func(super::super::interrupt::irq::pit); - - (freq_numer, freq_denom_in_s) - } } #[repr(u8)] @@ -303,30 +219,3 @@ pub enum LvtTimerMode { Periodic = 0b01, TscDeadline = 0b10, } - -/// Find the most suitable divider configuration value, which is useful if the reported frequency -/// is way too high to actually be useful. -fn most_suitable_divider(freq: u64) -> u8 { - // the current scheduler switches process about every 40 µs, with 4 µs per tick. - let quotient = (freq * 1000) / 2_000_000_000; - if quotient == 0 { - // the frequency is way to low, so the pit should be used - println!("Suboptimal APIC timer frequency"); - 0b1011 // divide by 1 - } else if quotient == 1 { - // the frequency closely matches the requested frequency, so use divider 1 - 0b1011 - } else if quotient < 4 { - 0b0000 // divider 2 - } else if quotient < 8 { - 0b0001 // divider 4 - } else if quotient < 16 { - 0b0010 // divider 8 - } else if quotient < 32 { - 0b0011 // divider 16 - } else if quotient < 64 { - 0b1001 // divider 64 - } else { - 0b1010 // divider 128 - } -} diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index b3784e6..18ee836 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -43,7 +43,7 @@ pub extern fn irq_trigger(irq: u8) { let guard = HANDLES.read(); if let Some(handles) = guard.as_ref() { - for (fd, (_, handle_irq)) in handles.iter().filter_map(|(fd, handle)| Some((fd, handle.as_irq_handle()?))).filter(|&(_, (_, handle_irq))| handle_irq == irq) { + for (fd, _) in handles.iter().filter_map(|(fd, handle)| Some((fd, handle.as_irq_handle()?))).filter(|&(_, (_, handle_irq))| handle_irq == irq) { event::trigger(IRQ_SCHEME_ID.load(Ordering::SeqCst), *fd, EVENT_READ); } } else { From 0fd24f60610e8e3b7e07cb6ef165cc149b71db92 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 4 Apr 2020 10:57:00 +0200 Subject: [PATCH 8/8] Cleanup. --- src/arch/x86_64/idt.rs | 17 ++--------------- src/arch/x86_64/interrupt/irq.rs | 1 - 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs index 662cf2f..9c70db1 100644 --- a/src/arch/x86_64/idt.rs +++ b/src/arch/x86_64/idt.rs @@ -43,7 +43,7 @@ pub fn set_reserved(index: u8, reserved: bool) { } pub fn allocate_interrupt() -> Option { - for number in 50..=255 { + for number in 50..=254 { if ! is_reserved(number) { set_reserved(number, true); return Some(unsafe { NonZeroU8::new_unchecked(number) }); @@ -53,20 +53,7 @@ pub fn allocate_interrupt() -> Option { } pub fn available_irqs_iter() -> impl Iterator + 'static { - AvailableIrqsIter { index: Some(50) }.filter(|&index| !is_reserved(index)) -} - -struct AvailableIrqsIter { - index: Option, -} -impl Iterator for AvailableIrqsIter { - type Item = u8; - - fn next(&mut self) -> Option { - let index = self.index?; - self.index = index.checked_add(1); - Some(index) - } + (50..=254).filter(|&index| !is_reserved(index)) } macro_rules! use_irq( diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs index 4d8f86c..72c2972 100644 --- a/src/arch/x86_64/interrupt/irq.rs +++ b/src/arch/x86_64/interrupt/irq.rs @@ -167,7 +167,6 @@ macro_rules! allocatable_irq( ); pub unsafe fn allocatable_irq_generic(number: u8) { - println!("generic irq: {}", number); irq_trigger(number - 32); lapic_eoi(); }