diff --git a/Cargo.lock b/Cargo.lock index ce392fa..6c712c1 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.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.52" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -28,10 +28,10 @@ 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)", - "raw-cpuid 4.0.0 (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 8.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", @@ -41,7 +41,7 @@ dependencies = [ [[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)", @@ -52,41 +52,23 @@ name = "plain" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "proc-macro2" -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)", -] - -[[package]] -name = "quote" -version = "1.0.2" -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 = "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)", - "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 = "raw-cpuid" version = "7.0.3" 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.52 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "raw-cpuid" +version = "8.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.52 (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 +76,7 @@ dependencies = [ 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,26 +113,11 @@ name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "serde" -version = "1.0.101" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde_derive" -version = "1.0.101" -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)", -] - [[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,51 +131,30 @@ name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "syn" -version = "1.0.5" -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)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "x86" 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.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 bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a165d606cf084741d4ac3a28fb6e9b1eb0bd31f6cd999098cfddb0b2ab381dc0" -"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 bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum cc 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)" = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d" "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 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 raw-cpuid 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e9c0f2091b865a94bc3c9d34896cc4bbda04453453c391f7eb224491be9ae1d" "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 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 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/Cargo.toml b/Cargo.toml index 56c27a8..2997002 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["staticlib"] [dependencies] bitflags = "1.0.3" linked_list_allocator = "0.6.2" -raw-cpuid = "4.0.0" +raw-cpuid = "8.0.0" redox_syscall = { path = "syscall" } slab_allocator = { path = "slab_allocator", optional = true } spin = "0.4.8" diff --git a/src/arch/x86_64/device/pic.rs b/src/arch/x86_64/device/pic.rs index 2518550..12e68a6 100644 --- a/src/arch/x86_64/device/pic.rs +++ b/src/arch/x86_64/device/pic.rs @@ -70,4 +70,9 @@ impl Pic { mask &= !(1 << irq); self.data.write(mask); } + /// A bitmap of all currently servicing IRQs. Spurious IRQs will not have this bit set + pub fn isr(&mut self) -> u8 { + self.cmd.write(0x0A); + self.cmd.read() // note that cmd is read, rather than data + } } diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs index 9c70db1..e1c0095 100644 --- a/src/arch/x86_64/idt.rs +++ b/src/arch/x86_64/idt.rs @@ -1,5 +1,9 @@ -use core::mem; use core::num::NonZeroU8; +use core::sync::atomic::{AtomicU64, Ordering}; +use core::mem; + +use alloc::boxed::Box; +use alloc::collections::BTreeMap; use x86::segmentation::Descriptor as X86IdtEntry; use x86::dtables::{self, DescriptorTablePointer}; @@ -7,65 +11,112 @@ use x86::dtables::{self, DescriptorTablePointer}; use crate::interrupt::*; use crate::ipi::IpiKind; -use spin::Mutex; +use spin::RwLock; pub static mut INIT_IDTR: DescriptorTablePointer = DescriptorTablePointer { limit: 0, base: 0 as *const X86IdtEntry }; +#[thread_local] pub static mut IDTR: DescriptorTablePointer = DescriptorTablePointer { limit: 0, 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 type IdtEntries = [IdtEntry; 256]; +pub type IdtReservations = [AtomicU64; 4]; -pub static mut IDT: [IdtEntry; 256] = [IdtEntry::new(); 256]; -pub static IDT_RESERVATIONS: Mutex<[u64; 256 / 64]> = Mutex::new([0u64; 256 / 64]); +#[repr(packed)] +pub struct Idt { + entries: IdtEntries, + reservations: IdtReservations, +} +impl Idt { + pub const fn new() -> Self { + Self { + entries: [IdtEntry::new(); 256], + reservations: new_idt_reservations(), + } + } + #[inline] + pub fn is_reserved(&self, index: u8) -> bool { + let byte_index = index / 64; + let bit = index % 64; + + unsafe { &self.reservations[usize::from(byte_index)] }.load(Ordering::Acquire) & (1 << bit) != 0 + } + + #[inline] + pub fn set_reserved(&self, index: u8, reserved: bool) { + let byte_index = index / 64; + let bit = index % 64; + + unsafe { &self.reservations[usize::from(byte_index)] }.fetch_or(u64::from(reserved) << bit, Ordering::AcqRel); + } + #[inline] + pub fn is_reserved_mut(&mut self, index: u8) -> bool { + let byte_index = index / 64; + let bit = index % 64; + + *unsafe { &mut self.reservations[usize::from(byte_index)] }.get_mut() & (1 << bit) != 0 + } + + #[inline] + pub fn set_reserved_mut(&mut self, index: u8, reserved: bool) { + let byte_index = index / 64; + let bit = index % 64; + + *unsafe { &mut self.reservations[usize::from(byte_index)] }.get_mut() |= u64::from(reserved) << bit; + } +} + +static mut INIT_BSP_IDT: Idt = Idt::new(); + +// TODO: VecMap? +pub static IDTS: RwLock>> = RwLock::new(None); #[inline] -pub fn is_reserved(index: u8) -> bool { +pub fn is_reserved(cpu_id: usize, index: u8) -> bool { let byte_index = index / 64; let bit = index % 64; - IDT_RESERVATIONS.lock()[usize::from(byte_index)] & (1 << bit) != 0 + unsafe { &IDTS.read().as_ref().unwrap().get(&cpu_id).unwrap().reservations[usize::from(byte_index)] }.load(Ordering::Acquire) & (1 << bit) != 0 } #[inline] -pub fn set_reserved(index: u8, reserved: bool) { +pub fn set_reserved(cpu_id: usize, index: u8, reserved: bool) { let byte_index = index / 64; let bit = index % 64; - IDT_RESERVATIONS.lock()[usize::from(byte_index)] |= u64::from(reserved) << bit; + unsafe { &IDTS.read().as_ref().unwrap().get(&cpu_id).unwrap().reservations[usize::from(byte_index)] }.fetch_or(u64::from(reserved) << bit, Ordering::AcqRel); } pub fn allocate_interrupt() -> Option { + let cpu_id = crate::cpu_id(); for number in 50..=254 { - if ! is_reserved(number) { - set_reserved(number, true); + if ! is_reserved(cpu_id, number) { + set_reserved(cpu_id, number, true); return Some(unsafe { NonZeroU8::new_unchecked(number) }); } } None } -pub fn available_irqs_iter() -> impl Iterator + 'static { - (50..=254).filter(|&index| !is_reserved(index)) +pub fn available_irqs_iter(cpu_id: usize) -> impl Iterator + 'static { + (32..=254).filter(move |&index| !is_reserved(cpu_id, index)) } macro_rules! use_irq( - ( $number:literal, $func:ident ) => { - IDT[$number].set_func($func); - } + ( $idt: expr, $number:literal, $func:ident ) => {{ + $idt[$number].set_func($func); + }} ); macro_rules! use_default_irqs( - () => {{ + ($idt:expr) => {{ use crate::interrupt::irq::*; - default_irqs!(use_irq); + default_irqs!($idt, use_irq); }} ); @@ -73,79 +124,111 @@ pub unsafe fn init() { dtables::lidt(&INIT_IDTR); } -pub unsafe fn init_paging() { - IDTR.limit = (IDT.len() * mem::size_of::() - 1) as u16; - IDTR.base = IDT.as_ptr() as *const X86IdtEntry; +const fn new_idt_reservations() -> [AtomicU64; 4] { + [AtomicU64::new(0), AtomicU64::new(0), AtomicU64::new(0), AtomicU64::new(0)] +} + +/// Initialize the IDT for a +pub unsafe fn init_paging_post_heap(is_bsp: bool, cpu_id: usize) { + let mut idts_guard = IDTS.write(); + let idts_btree = idts_guard.get_or_insert_with(|| BTreeMap::new()); + + if is_bsp { + idts_btree.insert(cpu_id, &mut INIT_BSP_IDT); + } else { + let idt = idts_btree.entry(cpu_id).or_insert_with(|| Box::leak(Box::new(Idt::new()))); + init_generic(is_bsp, idt); + } +} + +/// Initializes a fully functional IDT for use before it be moved into the map. This is ONLY called +/// on the BSP, since the kernel heap is ready for the APs. +pub unsafe fn init_paging_bsp() { + init_generic(true, &mut INIT_BSP_IDT); +} + +/// Initializes an IDT for any type of processor. +pub unsafe fn init_generic(is_bsp: bool, idt: &mut Idt) { + let (current_idt, current_reservations) = (&mut idt.entries, &mut idt.reservations); + + IDTR.limit = (current_idt.len() * mem::size_of::() - 1) as u16; + IDTR.base = current_idt.as_ptr() as *const X86IdtEntry; // Set up exceptions - IDT[0].set_func(exception::divide_by_zero); - IDT[1].set_func(exception::debug); - IDT[2].set_func(exception::non_maskable); - IDT[3].set_func(exception::breakpoint); - IDT[3].set_flags(IdtFlags::PRESENT | IdtFlags::RING_3 | IdtFlags::INTERRUPT); - IDT[4].set_func(exception::overflow); - IDT[5].set_func(exception::bound_range); - IDT[6].set_func(exception::invalid_opcode); - IDT[7].set_func(exception::device_not_available); - IDT[8].set_func(exception::double_fault); + current_idt[0].set_func(exception::divide_by_zero); + current_idt[1].set_func(exception::debug); + current_idt[2].set_func(exception::non_maskable); + current_idt[3].set_func(exception::breakpoint); + current_idt[3].set_flags(IdtFlags::PRESENT | IdtFlags::RING_3 | IdtFlags::INTERRUPT); + current_idt[4].set_func(exception::overflow); + current_idt[5].set_func(exception::bound_range); + current_idt[6].set_func(exception::invalid_opcode); + current_idt[7].set_func(exception::device_not_available); + current_idt[8].set_func(exception::double_fault); // 9 no longer available - IDT[10].set_func(exception::invalid_tss); - IDT[11].set_func(exception::segment_not_present); - IDT[12].set_func(exception::stack_segment); - IDT[13].set_func(exception::protection); - IDT[14].set_func(exception::page); + current_idt[10].set_func(exception::invalid_tss); + current_idt[11].set_func(exception::segment_not_present); + current_idt[12].set_func(exception::stack_segment); + current_idt[13].set_func(exception::protection); + current_idt[14].set_func(exception::page); // 15 reserved - IDT[16].set_func(exception::fpu); - IDT[17].set_func(exception::alignment_check); - IDT[18].set_func(exception::machine_check); - IDT[19].set_func(exception::simd); - IDT[20].set_func(exception::virtualization); + current_idt[16].set_func(exception::fpu); + current_idt[17].set_func(exception::alignment_check); + current_idt[18].set_func(exception::machine_check); + current_idt[19].set_func(exception::simd); + current_idt[20].set_func(exception::virtualization); // 21 through 29 reserved - IDT[30].set_func(exception::security); + current_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; + *current_reservations[0].get_mut() |= 0x0000_0000_FFFF_FFFF; - // Set up IRQs - IDT[32].set_func(irq::pit); - IDT[33].set_func(irq::keyboard); - IDT[34].set_func(irq::cascade); - IDT[35].set_func(irq::com2); - IDT[36].set_func(irq::com1); - IDT[37].set_func(irq::lpt2); - IDT[38].set_func(irq::floppy); - IDT[39].set_func(irq::lpt1); - IDT[40].set_func(irq::rtc); - IDT[41].set_func(irq::pci1); - IDT[42].set_func(irq::pci2); - IDT[43].set_func(irq::pci3); - IDT[44].set_func(irq::mouse); - 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); + if is_bsp { + // Set up IRQs + current_idt[32].set_func(irq::pit); + current_idt[33].set_func(irq::keyboard); + current_idt[34].set_func(irq::cascade); + current_idt[35].set_func(irq::com2); + current_idt[36].set_func(irq::com1); + current_idt[37].set_func(irq::lpt2); + current_idt[38].set_func(irq::floppy); + current_idt[39].set_func(irq::lpt1); + current_idt[40].set_func(irq::rtc); + current_idt[41].set_func(irq::pci1); + current_idt[42].set_func(irq::pci2); + current_idt[43].set_func(irq::pci3); + current_idt[44].set_func(irq::mouse); + current_idt[45].set_func(irq::fpu); + current_idt[46].set_func(irq::ata1); + current_idt[47].set_func(irq::ata2); + current_idt[48].set_func(irq::lapic_timer); + current_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; + // reserve bits 49:32, which are for the standard IRQs, and for the local apic timer and error. + *current_reservations[0].get_mut() |= 0x0003_FFFF_0000_0000; + } else { + // TODO: use_default_irqs! but also the legacy IRQs that are only needed on one CPU + } + + use_default_irqs!(current_idt); // 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); + current_idt[IpiKind::Wakeup as usize].set_func(ipi::wakeup); + current_idt[IpiKind::Switch as usize].set_func(ipi::switch); + current_idt[IpiKind::Tlb as usize].set_func(ipi::tlb); + current_idt[IpiKind::Pit as usize].set_func(ipi::pit); + idt.set_reserved_mut(IpiKind::Wakeup as u8, true); + idt.set_reserved_mut(IpiKind::Switch as u8, true); + idt.set_reserved_mut(IpiKind::Tlb as u8, true); + idt.set_reserved_mut(IpiKind::Pit as u8, true); + let current_idt = &mut idt.entries; // Set syscall function - IDT[0x80].set_func(syscall::syscall); - IDT[0x80].set_flags(IdtFlags::PRESENT | IdtFlags::RING_3 | IdtFlags::INTERRUPT); - set_reserved(0x80, true); + current_idt[0x80].set_func(syscall::syscall); + current_idt[0x80].set_flags(IdtFlags::PRESENT | IdtFlags::RING_3 | IdtFlags::INTERRUPT); + idt.set_reserved_mut(0x80, true); dtables::lidt(&IDTR); } @@ -163,7 +246,7 @@ bitflags! { } } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Default)] #[repr(packed)] pub struct IdtEntry { offsetl: u16, diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs index fe53f7a..d604e0d 100644 --- a/src/arch/x86_64/interrupt/irq.rs +++ b/src/arch/x86_64/interrupt/irq.rs @@ -1,5 +1,7 @@ use core::sync::atomic::{AtomicUsize, Ordering}; +use alloc::vec::Vec; + use crate::context::timeout; use crate::device::{local_apic, ioapic, pic}; use crate::device::serial::{COM1, COM2}; @@ -48,11 +50,33 @@ unsafe fn ps2_interrupt(index: usize) { } #[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum IrqMethod { Pic = 0, Apic = 1, } +static SPURIOUS_COUNT_IRQ7: AtomicUsize = AtomicUsize::new(0); +static SPURIOUS_COUNT_IRQ15: AtomicUsize = AtomicUsize::new(0); + +pub fn spurious_count_irq7() -> usize { + SPURIOUS_COUNT_IRQ7.load(Ordering::Relaxed) +} +pub fn spurious_count_irq15() -> usize { + SPURIOUS_COUNT_IRQ15.load(Ordering::Relaxed) +} +pub fn spurious_count() -> usize { + spurious_count_irq7() + spurious_count_irq15() +} +pub fn spurious_irq_resource() -> syscall::Result> { + match irq_method() { + IrqMethod::Apic => Ok(Vec::from(&b"(not implemented for APIC yet)"[..])), + IrqMethod::Pic => { + Ok(format!("{}\tIRQ7\n{}\tIRQ15\n{}\ttotal\n", spurious_count_irq7(), spurious_count_irq15(), spurious_count()).into_bytes()) + } + } +} + static IRQ_METHOD: AtomicUsize = AtomicUsize::new(IrqMethod::Pic as usize); pub fn set_irq_method(method: IrqMethod) { @@ -120,16 +144,8 @@ unsafe fn pic_eoi(irq: u8) { if irq >= 8 { pic::MASTER.ack(); - if irq == 15 { - //TODO: check spurious - return; - } pic::SLAVE.ack(); } else { - if irq == 7 { - //TODO: check spurious - return; - } pic::MASTER.ack(); } } @@ -213,6 +229,11 @@ interrupt!(floppy, { }); interrupt!(lpt1, { + if irq_method() == IrqMethod::Pic && pic::MASTER.isr() & (1 << 7) == 0 { + // the IRQ was spurious, ignore it but increment a counter. + SPURIOUS_COUNT_IRQ7.fetch_add(1, Ordering::Relaxed); + return; + } trigger(7); eoi(7); }); @@ -253,6 +274,11 @@ interrupt!(ata1, { }); interrupt!(ata2, { + if irq_method() == IrqMethod::Pic && pic::SLAVE.isr() & (1 << 7) == 0 { + SPURIOUS_COUNT_IRQ15.fetch_add(1, Ordering::Relaxed); + pic::MASTER.ack(); + return + } trigger(15); eoi(15); }); @@ -282,7 +308,7 @@ interrupt!(calib_pit, { // XXX: This would look way prettier using const generics. macro_rules! allocatable_irq( - ( $number:literal, $name:ident ) => { + ( $idt:expr, $number:literal, $name:ident ) => { interrupt!($name, { allocatable_irq_generic($number); }); diff --git a/src/arch/x86_64/macros.rs b/src/arch/x86_64/macros.rs index d3d50b6..84021f6 100644 --- a/src/arch/x86_64/macros.rs +++ b/src/arch/x86_64/macros.rs @@ -394,9 +394,9 @@ macro_rules! interrupt_error { } #[macro_export] macro_rules! irqs( - ( [ $( ($number:literal, $name:ident) ,)* ], $submac:ident ) => { + ( [ $( ($idt:expr, $number:literal, $name:ident) ,)* ], $submac:ident ) => { $( - $submac!($number, $name); + $submac!($idt, $number, $name); )* } ); @@ -405,42 +405,42 @@ macro_rules! irqs( // allocatable_irq_NUM. #[macro_export] macro_rules! default_irqs( - ($submac:ident) => { + ($idt:expr, $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), + ($idt, 50, irq_50), ($idt, 51, irq_51), ($idt, 52, irq_52), ($idt, 53, irq_53), ($idt, 54, irq_54), ($idt, 55, irq_55), ($idt, 56, irq_56), ($idt, 57, irq_57), ($idt, 58, irq_58), ($idt, 59, irq_59), + ($idt, 60, irq_60), ($idt, 61, irq_61), ($idt, 62, irq_62), ($idt, 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), + ($idt, 68, irq_68), ($idt, 69, irq_69), + ($idt, 70, irq_70), ($idt, 71, irq_71), ($idt, 72, irq_72), ($idt, 73, irq_73), ($idt, 74, irq_74), ($idt, 75, irq_75), ($idt, 76, irq_76), ($idt, 77, irq_77), ($idt, 78, irq_78), ($idt, 79, irq_79), + ($idt, 80, irq_80), ($idt, 81, irq_81), ($idt, 82, irq_82), ($idt, 83, irq_83), ($idt, 84, irq_84), ($idt, 85, irq_85), ($idt, 86, irq_86), ($idt, 87, irq_87), ($idt, 88, irq_88), ($idt, 89, irq_89), + ($idt, 90, irq_90), ($idt, 91, irq_91), ($idt, 92, irq_92), ($idt, 93, irq_93), ($idt, 94, irq_94), ($idt, 95, irq_95), ($idt, 96, irq_96), ($idt, 97, irq_97), ($idt, 98, irq_98), ($idt, 99, irq_99), + ($idt, 100, irq_100), ($idt, 101, irq_101), ($idt, 102, irq_102), ($idt, 103, irq_103), ($idt, 104, irq_104), ($idt, 105, irq_105), ($idt, 106, irq_106), ($idt, 107, irq_107), ($idt, 108, irq_108), ($idt, 109, irq_109), + ($idt, 110, irq_110), ($idt, 111, irq_111), ($idt, 112, irq_112), ($idt, 113, irq_113), ($idt, 114, irq_114), ($idt, 115, irq_115), ($idt, 116, irq_116), ($idt, 117, irq_117), ($idt, 118, irq_118), ($idt, 119, irq_119), + ($idt, 120, irq_120), ($idt, 121, irq_121), ($idt, 122, irq_122), ($idt, 123, irq_123), ($idt, 124, irq_124), ($idt, 125, irq_125), ($idt, 126, irq_126), ($idt, 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), + ($idt, 129, irq_129), + ($idt, 130, irq_130), ($idt, 131, irq_131), ($idt, 132, irq_132), ($idt, 133, irq_133), ($idt, 134, irq_134), ($idt, 135, irq_135), ($idt, 136, irq_136), ($idt, 137, irq_137), ($idt, 138, irq_138), ($idt, 139, irq_139), + ($idt, 140, irq_140), ($idt, 141, irq_141), ($idt, 142, irq_142), ($idt, 143, irq_143), ($idt, 144, irq_144), ($idt, 145, irq_145), ($idt, 146, irq_146), ($idt, 147, irq_147), ($idt, 148, irq_148), ($idt, 149, irq_149), + ($idt, 150, irq_150), ($idt, 151, irq_151), ($idt, 152, irq_152), ($idt, 153, irq_153), ($idt, 154, irq_154), ($idt, 155, irq_155), ($idt, 156, irq_156), ($idt, 157, irq_157), ($idt, 158, irq_158), ($idt, 159, irq_159), + ($idt, 160, irq_160), ($idt, 161, irq_161), ($idt, 162, irq_162), ($idt, 163, irq_163), ($idt, 164, irq_164), ($idt, 165, irq_165), ($idt, 166, irq_166), ($idt, 167, irq_167), ($idt, 168, irq_168), ($idt, 169, irq_169), + ($idt, 170, irq_170), ($idt, 171, irq_171), ($idt, 172, irq_172), ($idt, 173, irq_173), ($idt, 174, irq_174), ($idt, 175, irq_175), ($idt, 176, irq_176), ($idt, 177, irq_177), ($idt, 178, irq_178), ($idt, 179, irq_179), + ($idt, 180, irq_180), ($idt, 181, irq_181), ($idt, 182, irq_182), ($idt, 183, irq_183), ($idt, 184, irq_184), ($idt, 185, irq_185), ($idt, 186, irq_186), ($idt, 187, irq_187), ($idt, 188, irq_188), ($idt, 189, irq_189), + ($idt, 190, irq_190), ($idt, 191, irq_191), ($idt, 192, irq_192), ($idt, 193, irq_193), ($idt, 194, irq_194), ($idt, 195, irq_195), ($idt, 196, irq_196), ($idt, 197, irq_197), ($idt, 198, irq_198), ($idt, 199, irq_199), + ($idt, 200, irq_200), ($idt, 201, irq_201), ($idt, 202, irq_202), ($idt, 203, irq_203), ($idt, 204, irq_204), ($idt, 205, irq_205), ($idt, 206, irq_206), ($idt, 207, irq_207), ($idt, 208, irq_208), ($idt, 209, irq_209), + ($idt, 210, irq_210), ($idt, 211, irq_211), ($idt, 212, irq_212), ($idt, 213, irq_213), ($idt, 214, irq_214), ($idt, 215, irq_215), ($idt, 216, irq_216), ($idt, 217, irq_217), ($idt, 218, irq_218), ($idt, 219, irq_219), + ($idt, 220, irq_220), ($idt, 221, irq_221), ($idt, 222, irq_222), ($idt, 223, irq_223), ($idt, 224, irq_224), ($idt, 225, irq_225), ($idt, 226, irq_226), ($idt, 227, irq_227), ($idt, 228, irq_228), ($idt, 229, irq_229), + ($idt, 230, irq_230), ($idt, 231, irq_231), ($idt, 232, irq_232), ($idt, 233, irq_233), ($idt, 234, irq_234), ($idt, 235, irq_235), ($idt, 236, irq_236), ($idt, 237, irq_237), ($idt, 238, irq_238), ($idt, 239, irq_239), + ($idt, 240, irq_240), ($idt, 241, irq_241), ($idt, 242, irq_242), ($idt, 243, irq_243), ($idt, 244, irq_244), ($idt, 245, irq_245), ($idt, 246, irq_246), ($idt, 247, irq_247), ($idt, 248, irq_248), ($idt, 249, irq_249), + ($idt, 250, irq_250), ($idt, 251, irq_251), ($idt, 252, irq_252), ($idt, 253, irq_253), ($idt, 254, irq_254), ($idt, 255, irq_255), ], $submac); } ); macro_rules! define_default_irqs( () => { - default_irqs!(allocatable_irq); + default_irqs!((), allocatable_irq); } ); diff --git a/src/arch/x86_64/start.rs b/src/arch/x86_64/start.rs index 11f8404..8438079 100644 --- a/src/arch/x86_64/start.rs +++ b/src/arch/x86_64/start.rs @@ -109,7 +109,7 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! { gdt::init_paging(tcb_offset, stack_base + stack_size); // Set up IDT - idt::init_paging(); + idt::init_paging_bsp(); // Set up syscall instruction interrupt::syscall::init(); @@ -132,6 +132,8 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! { // Setup kernel heap allocator::init(&mut active_table); + idt::init_paging_post_heap(true, 0); + // Activate memory logging log::init(); @@ -200,7 +202,7 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! { gdt::init_paging(tcb_offset, stack_end); // Set up IDT for AP - idt::init_paging(); + idt::init_paging_post_heap(false, cpu_id); // Set up syscall instruction interrupt::syscall::init(); diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index 18ee836..87309ad 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -1,11 +1,13 @@ use core::{mem, str}; +use core::str::FromStr; use core::sync::atomic::{AtomicUsize, Ordering}; -use spin::{Mutex, RwLock}; use alloc::collections::BTreeMap; use alloc::vec::Vec; use alloc::string::String; +use spin::{Mutex, RwLock}; + use crate::arch::interrupt::{available_irqs_iter, bsp_apic_id, is_reserved, set_reserved}; use crate::event; @@ -33,8 +35,9 @@ const BASE_IRQ_COUNT: u8 = 16; /// are only freed when the file descriptor is closed. const TOTAL_IRQ_COUNT: u8 = 224; +const INO_TOPLEVEL: u64 = 0x8002_0000_0000_0000; const INO_AVAIL: u64 = 0x8000_0000_0000_0000; -const INO_BSP: u64 = 0x8000_0000_0000_0001; +const INO_BSP: u64 = 0x8001_0000_0000_0000; /// Add to the input queue #[no_mangle] @@ -56,7 +59,8 @@ enum Handle { ack: AtomicUsize, irq: u8, }, - Avail(Vec, AtomicUsize), + Avail(u8, Vec, AtomicUsize), // CPU id, data, offset + TopLevel(Vec, AtomicUsize), // data, offset Bsp, } impl Handle { @@ -70,6 +74,7 @@ impl Handle { pub struct IrqScheme { next_fd: AtomicUsize, + cpus: Vec, } impl IrqScheme { @@ -78,10 +83,51 @@ impl IrqScheme { *HANDLES.write() = Some(BTreeMap::new()); + let cpus = if cfg!(feature = "acpi") { + use crate::acpi::madt::*; + + let madt: &Madt = unsafe { MADT.as_ref().unwrap() }; + + madt.iter().filter_map(|entry| match entry { + MadtEntry::LocalApic(apic) => Some(apic.id), + _ => None, + }).collect::>() + } else { + vec!(0) + }; + IrqScheme { next_fd: AtomicUsize::new(0), + cpus, } } + fn open_ext_irq(flags: usize, cpu_id: u8, path_str: &str) -> Result { + let irq_number = u8::from_str(path_str).or(Err(Error::new(ENOENT)))?; + + Ok(if irq_number < BASE_IRQ_COUNT && Some(u32::from(cpu_id)) == bsp_apic_id() { + // Give legacy IRQs only to `irq:{0..15}` and `irq:cpu-/{0..15}` (same handles). + // + // The only CPUs don't have the legacy IRQs in their IDTs. + + Handle::Irq { + ack: AtomicUsize::new(0), + irq: irq_number, + } + } else if irq_number < 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(usize::from(cpu_id), irq_to_vector(irq_number)) { + return Err(Error::new(EEXIST)); + } + set_reserved(usize::from(cpu_id), irq_to_vector(irq_number), true); + } + Handle::Irq { ack: AtomicUsize::new(0), irq: irq_number } + } else { + return Err(Error::new(ENOENT)); + }) + } } const fn irq_to_vector(irq: u8) -> u8 { @@ -98,42 +144,60 @@ impl Scheme for IrqScheme { let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; let path_str = path_str.trim_start_matches('/'); - let handle = if (flags & O_DIRECTORY != 0 || flags & O_STAT != 0) && path_str.is_empty() { - // list all of the allocatable IRQs + let handle: Handle = if path_str.is_empty() { + if flags & O_DIRECTORY == 0 && flags & O_STAT == 0 { return Err(Error::new(EISDIR)) } + + // list every logical CPU in the format of e.g. `cpu-1b` 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(); + for cpu_id in &self.cpus { + writeln!(bytes, "cpu-{:02x}", cpu_id); } - Handle::Avail(bytes.into_bytes(), AtomicUsize::new(0)) + if bsp_apic_id().is_some() { + writeln!(bytes, "bsp").unwrap(); + } + + // TODO: When signals are used for IRQs, there will probably also be a file + // `irq:signal` that maps IRQ numbers and their source APIC IDs to signal numbers. + + Handle::TopLevel(bytes.into_bytes(), AtomicUsize::new(0)) } else { 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 { + } else if path_str.starts_with("cpu-") { + let path_str = &path_str[4..]; + let cpu_id = u8::from_str_radix(&path_str[..2], 16).or(Err(Error::new(ENOENT)))?; + let path_str = path_str[2..].trim_end_matches('/'); - if is_reserved(irq_to_vector(id)) { - return Err(Error::new(EEXIST)); + if path_str.is_empty() { + let mut data = String::new(); + use core::fmt::Write; + + for vector in available_irqs_iter(cpu_id.into()) { + let irq = vector_to_irq(vector); + if Some(u32::from(cpu_id)) == bsp_apic_id() && irq < BASE_IRQ_COUNT { + continue; } - set_reserved(irq_to_vector(id), true); + writeln!(data, "{}", irq); } - Handle::Irq { ack: AtomicUsize::new(0), irq: id } + + Handle::Avail(cpu_id, data.into_bytes(), AtomicUsize::new(0)) + } else if path_str.chars().next() == Some('/') { + let path_str = &path_str[1..]; + Self::open_ext_irq(flags, cpu_id, path_str)? + } else { + return Err(Error::new(ENOENT)); + } + } else if let Ok(plain_irq_number) = u8::from_str(path_str) { + if plain_irq_number < BASE_IRQ_COUNT { + Handle::Irq { ack: AtomicUsize::new(0), irq: plain_irq_number } } else { return Err(Error::new(ENOENT)); } @@ -176,7 +240,7 @@ impl Scheme for IrqScheme { return Err(Error::new(EBADFD)); } } - &Handle::Avail(ref buf, ref offset) => { + &Handle::Avail(_, ref buf, ref offset) | &Handle::TopLevel(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; @@ -192,7 +256,7 @@ impl Scheme for IrqScheme { let handle = handles_guard.as_ref().unwrap().get(&id).ok_or(Error::new(EBADF))?; match handle { - &Handle::Avail(ref buf, ref offset) => { + &Handle::Avail(_, ref buf, ref offset) | &Handle::TopLevel(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()), @@ -245,7 +309,7 @@ impl Scheme for IrqScheme { stat.st_ino = handle_irq.into(); stat.st_nlink = 1; } - Handle::Bsp => { + &Handle::Bsp => { stat.st_mode = MODE_CHR | 0o400; stat.st_size = mem::size_of::() as u64; stat.st_blocks = 1; @@ -253,11 +317,17 @@ impl Scheme for IrqScheme { stat.st_ino = INO_BSP; stat.st_nlink = 1; } - Handle::Avail(ref buf, _) => { + &Handle::Avail(cpu_id, ref buf, _) => { + stat.st_mode = MODE_DIR | 0o700; + stat.st_size = buf.len() as u64; + stat.st_ino = INO_AVAIL | u64::from(cpu_id) << 32; + stat.st_nlink = 2; + } + &Handle::TopLevel(ref buf, _) => { stat.st_mode = MODE_DIR | 0o500; stat.st_size = buf.len() as u64; - stat.st_ino = INO_AVAIL; - stat.st_nlink = 2; + stat.st_ino = INO_TOPLEVEL; + stat.st_nlink = 1; } } Ok(0) @@ -278,8 +348,10 @@ impl Scheme for IrqScheme { let scheme_path = match handle { &Handle::Irq { irq, .. } => format!("irq:{}", irq), &Handle::Bsp => format!("irq:bsp"), - &Handle::Avail(_, _) => format!("irq:"), + &Handle::Avail(cpu_id, _, _) => format!("irq:cpu-{:2x}", cpu_id), + &Handle::TopLevel(_, _) => format!("irq:"), }.into_bytes(); + let mut i = 0; while i < buf.len() && i < scheme_path.len() { buf[i] = scheme_path[i]; @@ -298,7 +370,7 @@ impl Scheme for IrqScheme { if let &Handle::Irq { irq: handle_irq, .. } = handle { if handle_irq > BASE_IRQ_COUNT { - set_reserved(irq_to_vector(handle_irq), false); + set_reserved(0, irq_to_vector(handle_irq), false); } } Ok(0) diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs index d128b57..8b65632 100644 --- a/src/scheme/sys/mod.rs +++ b/src/scheme/sys/mod.rs @@ -9,6 +9,7 @@ use crate::syscall::data::Stat; use crate::syscall::error::{Error, EBADF, EINVAL, ENOENT, Result}; use crate::syscall::flag::{MODE_DIR, MODE_FILE, SEEK_CUR, SEEK_END, SEEK_SET}; use crate::syscall::scheme::Scheme; +use crate::arch::interrupt::irq; mod block; mod context; @@ -51,6 +52,7 @@ impl SysScheme { files.insert(b"scheme_num", Box::new(scheme_num::resource)); files.insert(b"syscall", Box::new(syscall::resource)); files.insert(b"uname", Box::new(uname::resource)); + files.insert(b"spurious_irq", Box::new(irq::spurious_irq_resource)); SysScheme { next_id: AtomicUsize::new(0),