From f044ffb03b656c454522f78d63cb5d04cd137eec Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 21 Feb 2025 14:16:58 +0100 Subject: [PATCH] Remove stable #![feature] and most x86_64 static mut. --- src/acpi/madt/mod.rs | 9 ++++-- src/arch/x86/interrupt/irq.rs | 20 ++++++------ src/arch/x86_64/gdt.rs | 2 +- src/arch/x86_64/interrupt/irq.rs | 20 ++++++------ src/arch/x86_64/start.rs | 17 +++++----- src/arch/x86_shared/device/ioapic.rs | 24 ++++++++++----- src/arch/x86_shared/device/pic.rs | 46 ++++++++++++++++++---------- src/arch/x86_shared/device/pit.rs | 27 +++++++++++----- src/main.rs | 3 -- src/scheme/irq.rs | 2 +- src/startup/memory.rs | 21 +++++++------ 11 files changed, 114 insertions(+), 77 deletions(-) diff --git a/src/acpi/madt/mod.rs b/src/acpi/madt/mod.rs index 47dcd85c3f..53e57f79d5 100644 --- a/src/acpi/madt/mod.rs +++ b/src/acpi/madt/mod.rs @@ -1,4 +1,4 @@ -use core::mem; +use core::{cell::SyncUnsafeCell, mem}; use super::{find_sdt, sdt::Sdt}; @@ -22,7 +22,10 @@ mod arch; #[path = "arch/other.rs"] mod arch; -pub static mut MADT: Option = None; +static MADT: SyncUnsafeCell> = SyncUnsafeCell::new(None); +pub fn madt() -> Option<&'static Madt> { + unsafe { &*MADT.get() }.as_ref() +} pub const FLAG_PCAT: u32 = 1; impl Madt { @@ -37,7 +40,7 @@ impl Madt { if let Some(madt) = madt { // safe because no APs have been started yet. - unsafe { MADT = Some(madt) }; + unsafe { MADT.get().write(Some(madt)) }; println!(" APIC: {:>08X}: {}", madt.local_address, madt.flags); diff --git a/src/arch/x86/interrupt/irq.rs b/src/arch/x86/interrupt/irq.rs index 2cfb81b7d3..99907dd009 100644 --- a/src/arch/x86/interrupt/irq.rs +++ b/src/arch/x86/interrupt/irq.rs @@ -114,9 +114,9 @@ unsafe fn pic_mask(irq: u8) { debug_assert!(irq < 16); if irq >= 8 { - pic::SLAVE.mask_set(irq - 8); + pic::slave().mask_set(irq - 8); } else { - pic::MASTER.mask_set(irq); + pic::master().mask_set(irq); } } @@ -128,10 +128,10 @@ unsafe fn pic_eoi(irq: u8) { debug_assert!(irq < 16); if irq >= 8 { - pic::MASTER.ack(); - pic::SLAVE.ack(); + pic::master().ack(); + pic::slave().ack(); } else { - pic::MASTER.ack(); + pic::master().ack(); } } @@ -143,9 +143,9 @@ unsafe fn pic_unmask(irq: usize) { debug_assert!(irq < 16); if irq >= 8 { - pic::SLAVE.mask_clear(irq as u8 - 8); + pic::slave().mask_clear(irq as u8 - 8); } else { - pic::MASTER.mask_clear(irq as u8); + pic::master().mask_clear(irq as u8); } } @@ -213,7 +213,7 @@ interrupt!(floppy, || { }); interrupt!(lpt1, || { - if irq_method() == IrqMethod::Pic && pic::MASTER.isr() & (1 << 7) == 0 { + 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; @@ -262,9 +262,9 @@ interrupt!(ata1, || { }); interrupt!(ata2, || { - if irq_method() == IrqMethod::Pic && pic::SLAVE.isr() & (1 << 7) == 0 { + if irq_method() == IrqMethod::Pic && pic::slave().isr() & (1 << 7) == 0 { SPURIOUS_COUNT_IRQ15.fetch_add(1, Ordering::Relaxed); - pic::MASTER.ack(); + pic::master().ack(); return; } trigger(15); diff --git a/src/arch/x86_64/gdt.rs b/src/arch/x86_64/gdt.rs index 902a514e7f..83c1e6dee5 100644 --- a/src/arch/x86_64/gdt.rs +++ b/src/arch/x86_64/gdt.rs @@ -44,7 +44,7 @@ pub const GDT_F_LONG_MODE: u8 = 1 << 5; const IOBITMAP_SIZE: u32 = 65536 / 8; -static mut INIT_GDT: [GdtEntry; 3] = [ +static INIT_GDT: [GdtEntry; 3] = [ // Null GdtEntry::new(0, 0, 0, 0), // Kernel code diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs index b769a36f85..dc4036e07e 100644 --- a/src/arch/x86_64/interrupt/irq.rs +++ b/src/arch/x86_64/interrupt/irq.rs @@ -114,9 +114,9 @@ unsafe fn pic_mask(irq: u8) { debug_assert!(irq < 16); if irq >= 8 { - pic::SLAVE.mask_set(irq - 8); + pic::slave().mask_set(irq - 8); } else { - pic::MASTER.mask_set(irq); + pic::master().mask_set(irq); } } @@ -128,10 +128,10 @@ unsafe fn pic_eoi(irq: u8) { debug_assert!(irq < 16); if irq >= 8 { - pic::MASTER.ack(); - pic::SLAVE.ack(); + pic::master().ack(); + pic::slave().ack(); } else { - pic::MASTER.ack(); + pic::master().ack(); } } @@ -143,9 +143,9 @@ unsafe fn pic_unmask(irq: usize) { debug_assert!(irq < 16); if irq >= 8 { - pic::SLAVE.mask_clear(irq as u8 - 8); + pic::slave().mask_clear(irq as u8 - 8); } else { - pic::MASTER.mask_clear(irq as u8); + pic::master().mask_clear(irq as u8); } } @@ -213,7 +213,7 @@ interrupt!(floppy, || { }); interrupt!(lpt1, || { - if irq_method() == IrqMethod::Pic && pic::MASTER.isr() & (1 << 7) == 0 { + 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; @@ -262,9 +262,9 @@ interrupt!(ata1, || { }); interrupt!(ata2, || { - if irq_method() == IrqMethod::Pic && pic::SLAVE.isr() & (1 << 7) == 0 { + if irq_method() == IrqMethod::Pic && pic::slave().isr() & (1 << 7) == 0 { SPURIOUS_COUNT_IRQ15.fetch_add(1, Ordering::Relaxed); - pic::MASTER.ack(); + pic::master().ack(); return; } trigger(15); diff --git a/src/arch/x86_64/start.rs b/src/arch/x86_64/start.rs index a29663ee68..ec5ab0cb83 100644 --- a/src/arch/x86_64/start.rs +++ b/src/arch/x86_64/start.rs @@ -3,7 +3,10 @@ /// It must create the IDT with the correct entries, those entries are /// defined in other files inside of the `arch` module use core::slice; -use core::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering}; +use core::{ + cell::SyncUnsafeCell, + sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering}, +}; use log::info; @@ -21,9 +24,9 @@ use crate::{ }; /// Test of zero values in BSS. -static mut BSS_TEST_ZERO: usize = 0; +static BSS_TEST_ZERO: SyncUnsafeCell = SyncUnsafeCell::new(0); /// Test of non-zero values in data. -static mut DATA_TEST_NONZERO: usize = usize::max_value(); +static DATA_TEST_NONZERO: SyncUnsafeCell = SyncUnsafeCell::new(usize::max_value()); pub static KERNEL_BASE: AtomicUsize = AtomicUsize::new(0); pub static KERNEL_SIZE: AtomicUsize = AtomicUsize::new(0); @@ -69,8 +72,8 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! { // BSS should already be zero { - assert_eq!(BSS_TEST_ZERO, 0); - assert_eq!(DATA_TEST_NONZERO, usize::max_value()); + assert_eq!(BSS_TEST_ZERO.get().read(), 0); + assert_eq!(DATA_TEST_NONZERO.get().read(), usize::max_value()); } KERNEL_BASE.store(args.kernel_base as usize, Ordering::SeqCst); @@ -262,8 +265,8 @@ pub unsafe extern "C" fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! { let _stack_start = args.stack_start as usize; let stack_end = args.stack_end as usize; - assert_eq!(BSS_TEST_ZERO, 0); - assert_eq!(DATA_TEST_NONZERO, usize::max_value()); + assert_eq!(BSS_TEST_ZERO.get().read(), 0); + assert_eq!(DATA_TEST_NONZERO.get().read(), usize::max_value()); // Set up GDT before paging gdt::init(); diff --git a/src/arch/x86_shared/device/ioapic.rs b/src/arch/x86_shared/device/ioapic.rs index db727ed84a..74fe13be8e 100644 --- a/src/arch/x86_shared/device/ioapic.rs +++ b/src/arch/x86_shared/device/ioapic.rs @@ -1,4 +1,4 @@ -use core::{fmt, ptr}; +use core::{cell::SyncUnsafeCell, fmt, ptr}; use alloc::vec::Vec; use spin::Mutex; @@ -83,6 +83,8 @@ pub struct IoApic { gsi_start: u32, count: u8, } +unsafe impl Send for IoApic {} +unsafe impl Sync for IoApic {} impl IoApic { #[allow(dead_code)] pub fn new(regs_base: *const u32, gsi_start: u32) -> Self { @@ -217,16 +219,20 @@ pub struct Override { // static mut because only the AP initializes the I/O Apic, and when that is done, it's solely // accessed immutably. -static mut IOAPICS: Option> = None; +static IOAPICS: SyncUnsafeCell>> = SyncUnsafeCell::new(None); // static mut for the same reason as above -static mut SRC_OVERRIDES: Option> = None; +static SRC_OVERRIDES: SyncUnsafeCell>> = SyncUnsafeCell::new(None); pub fn ioapics() -> &'static [IoApic] { - unsafe { IOAPICS.as_ref().map_or(&[], |vector| &vector[..]) } + unsafe { &*IOAPICS.get() } + .as_ref() + .map_or(&[], |vector| &vector[..]) } pub fn src_overrides() -> &'static [Override] { - unsafe { SRC_OVERRIDES.as_ref().map_or(&[], |vector| &vector[..]) } + unsafe { &*SRC_OVERRIDES.get() } + .as_ref() + .map_or(&[], |vector| &vector[..]) } #[cfg(feature = "acpi")] @@ -263,7 +269,7 @@ pub unsafe fn handle_ioapic(mapper: &mut KernelMapper, madt_ioapic: &'static Mad "mismatched ACPI MADT I/O APIC ID, and the ID reported by the I/O APIC" ); - IOAPICS.get_or_insert_with(Vec::new).push(ioapic); + (*IOAPICS.get()).get_or_insert_with(Vec::new).push(ioapic); } #[cfg(feature = "acpi")] pub unsafe fn handle_src_override(src_override: &'static MadtIntSrcOverride) { @@ -295,7 +301,9 @@ pub unsafe fn handle_src_override(src_override: &'static MadtIntSrcOverride) { polarity, trigger_mode, }; - SRC_OVERRIDES.get_or_insert_with(Vec::new).push(over); + (*SRC_OVERRIDES.get()) + .get_or_insert_with(Vec::new) + .push(over); } #[allow(dead_code)] @@ -305,7 +313,7 @@ pub unsafe fn init(active_table: &mut KernelMapper) { // search the madt for all IOAPICs. #[cfg(feature = "acpi")] { - let madt: &'static Madt = match madt::MADT.as_ref() { + let madt: &'static Madt = match madt::madt() { Some(m) => m, // TODO: Parse MP tables too. None => return, diff --git a/src/arch/x86_shared/device/pic.rs b/src/arch/x86_shared/device/pic.rs index 487229892e..79fe74b28a 100644 --- a/src/arch/x86_shared/device/pic.rs +++ b/src/arch/x86_shared/device/pic.rs @@ -1,43 +1,57 @@ +use core::cell::SyncUnsafeCell; + use crate::{ arch::interrupt::irq, syscall::io::{Io, Pio}, }; -pub static mut MASTER: Pic = Pic::new(0x20); -pub static mut SLAVE: Pic = Pic::new(0xA0); +static MASTER: SyncUnsafeCell = SyncUnsafeCell::new(Pic::new(0x20)); +static SLAVE: SyncUnsafeCell = SyncUnsafeCell::new(Pic::new(0xA0)); + +// SAFETY: must be main thread +pub unsafe fn master<'a>() -> &'a mut Pic { + &mut *MASTER.get() +} +// SAFETY: must be main thread +pub unsafe fn slave<'a>() -> &'a mut Pic { + &mut *SLAVE.get() +} pub unsafe fn init() { + let master = master(); + let slave = slave(); + // Start initialization - MASTER.cmd.write(0x11); - SLAVE.cmd.write(0x11); + master.cmd.write(0x11); + slave.cmd.write(0x11); // Set offsets - MASTER.data.write(0x20); - SLAVE.data.write(0x28); + master.data.write(0x20); + slave.data.write(0x28); // Set up cascade - MASTER.data.write(4); - SLAVE.data.write(2); + master.data.write(4); + slave.data.write(2); // Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI) - MASTER.data.write(1); - SLAVE.data.write(1); + master.data.write(1); + slave.data.write(1); // Unmask interrupts - MASTER.data.write(0); - SLAVE.data.write(0); + master.data.write(0); + slave.data.write(0); // Ack remaining interrupts - MASTER.ack(); - SLAVE.ack(); + master.ack(); + slave.ack(); // probably already set to PIC, but double-check irq::set_irq_method(irq::IrqMethod::Pic); } pub unsafe fn disable() { - MASTER.data.write(0xFF); - SLAVE.data.write(0xFF); + master().data.write(0xFF); + slave().data.write(0xFF); } pub struct Pic { diff --git a/src/arch/x86_shared/device/pit.rs b/src/arch/x86_shared/device/pit.rs index 71dad3860e..e275a972c4 100644 --- a/src/arch/x86_shared/device/pit.rs +++ b/src/arch/x86_shared/device/pit.rs @@ -1,9 +1,20 @@ +use core::cell::SyncUnsafeCell; + use crate::syscall::io::{Io, Pio}; -pub static mut CHAN0: Pio = Pio::new(0x40); +static CHAN0: SyncUnsafeCell> = SyncUnsafeCell::new(Pio::new(0x40)); //pub static mut CHAN1: Pio = Pio::new(0x41); //pub static mut CHAN2: Pio = Pio::new(0x42); -pub static mut COMMAND: Pio = Pio::new(0x43); +static COMMAND: SyncUnsafeCell> = SyncUnsafeCell::new(Pio::new(0x43)); + +// SAFETY: must be externally syncd +pub unsafe fn chan0<'a>() -> &'a mut Pio { + &mut *CHAN0.get() +} +// SAFETY: must be externally syncd +pub unsafe fn command<'a>() -> &'a mut Pio { + &mut *COMMAND.get() +} const SELECT_CHAN0: u8 = 0b00 << 6; const ACCESS_LATCH: u8 = 0b00 << 4; @@ -20,15 +31,15 @@ pub const CHAN0_DIVISOR: u16 = 4847; pub const RATE: u128 = (CHAN0_DIVISOR as u128 * PERIOD_FS) / 1_000_000; pub unsafe fn init() { - COMMAND.write(SELECT_CHAN0 | ACCESS_LOHI | MODE_2); - CHAN0.write(CHAN0_DIVISOR as u8); - CHAN0.write((CHAN0_DIVISOR >> 8) as u8); + command().write(SELECT_CHAN0 | ACCESS_LOHI | MODE_2); + chan0().write(CHAN0_DIVISOR as u8); + chan0().write((CHAN0_DIVISOR >> 8) as u8); } pub unsafe fn read() -> u16 { - COMMAND.write(SELECT_CHAN0 | ACCESS_LATCH); - let low = CHAN0.read(); - let high = CHAN0.read(); + command().write(SELECT_CHAN0 | ACCESS_LATCH); + let low = chan0().read(); + let high = chan0().read(); let counter = ((high as u16) << 8) | (low as u16); // Counter is inverted, subtract from CHAN0_DIVISOR CHAN0_DIVISOR.saturating_sub(counter) diff --git a/src/main.rs b/src/main.rs index a42ec1cf3f..3ee4cd8e57 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,19 +42,16 @@ // Ensure that all must_use results are used #![deny(unused_must_use)] #![feature(allocator_api)] -#![feature(asm_const)] #![feature(core_intrinsics)] #![allow(internal_features)] #![feature(int_roundings)] #![feature(iter_next_chunk)] #![feature(let_chains)] #![feature(naked_functions)] -#![feature(new_uninit)] #![feature(sync_unsafe_cell)] #![feature(variant_count)] #![cfg_attr(not(test), no_std)] #![cfg_attr(not(test), no_main)] -#![feature(option_get_or_insert_default)] #![feature(array_chunks)] #![feature(if_let_guard)] #![feature(iterator_try_collect)] diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index 49a179d280..deeeedb71c 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -96,7 +96,7 @@ impl IrqScheme { let cpus = { use crate::acpi::madt::*; - match unsafe { MADT.as_ref() } { + match madt() { Some(madt) => madt .iter() .filter_map(|entry| match entry { diff --git a/src/startup/memory.rs b/src/startup/memory.rs index ce82bcc4be..59ed8dc725 100644 --- a/src/startup/memory.rs +++ b/src/startup/memory.rs @@ -4,9 +4,10 @@ use crate::{ startup::memory::BootloaderMemoryKind::Null, }; use core::{ + cell::SyncUnsafeCell, cmp::{max, min}, - mem, slice, - slice::Iter, + mem, + slice::{self, Iter}, }; use rmm::{ Arch, BumpAllocator, MemoryArea, PageFlags, PageMapper, PhysicalAddress, TableKind, @@ -127,14 +128,14 @@ impl MemoryMap { } } -static mut MEMORY_MAP: MemoryMap = MemoryMap { +static MEMORY_MAP: SyncUnsafeCell = SyncUnsafeCell::new(MemoryMap { entries: [MemoryEntry { start: 0, end: 0, kind: BootloaderMemoryKind::Null, }; 512], size: 0, -}; +}); fn align_up(x: usize) -> usize { (x.saturating_add(PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE @@ -146,7 +147,7 @@ fn align_down(x: usize) -> usize { pub fn register_memory_region(base: usize, size: usize, kind: BootloaderMemoryKind) { if kind != Null && size != 0 { log::debug!("Registering {:?} memory {:X} size {:X}", kind, base, size); - unsafe { MEMORY_MAP.register(base, size, kind) } + unsafe { (*MEMORY_MAP.get()).register(base, size, kind) } } } @@ -167,7 +168,7 @@ pub fn register_bootloader_areas(areas_base: usize, areas_size: usize) { } unsafe fn add_memory(areas: &mut [MemoryArea], area_i: &mut usize, mut area: MemoryEntry) { - for reservation in MEMORY_MAP.non_free() { + for reservation in (*MEMORY_MAP.get()).non_free() { if area.end > reservation.start && area.end <= reservation.end { log::info!( "Memory {:X}:{:X} overlaps with reservation {:X}:{:X}", @@ -304,7 +305,7 @@ unsafe fn map_memory(areas: &[MemoryArea], mut bump_allocator: &mut Bum } } - let kernel_area = MEMORY_MAP.kernel().unwrap(); + let kernel_area = (*MEMORY_MAP.get()).kernel().unwrap(); let kernel_base = kernel_area.start; let kernel_size = kernel_area.end - kernel_area.start; // Map kernel at KERNEL_OFFSET and identity map too @@ -324,7 +325,7 @@ unsafe fn map_memory(areas: &[MemoryArea], mut bump_allocator: &mut Bum flush.ignore(); // Not the active table } - for area in MEMORY_MAP.identity_mapped() { + for area in (*MEMORY_MAP.get()).identity_mapped() { let base = area.start; let size = area.end - area.start; for i in 0..size / PAGE_SIZE { @@ -339,7 +340,7 @@ unsafe fn map_memory(areas: &[MemoryArea], mut bump_allocator: &mut Bum } //map dev mem - for area in MEMORY_MAP.devices() { + for area in (*MEMORY_MAP.get()).devices() { let base = area.start; let size = area.end - area.start; for i in 0..size / PAGE_SIZE { @@ -399,7 +400,7 @@ pub unsafe fn init(low_limit: Option, high_limit: Option) { let mut area_i = 0; // Copy initial memory map, and page align it - for area in MEMORY_MAP.free() { + for area in (*MEMORY_MAP.get()).free() { log::debug!("{:X}:{:X}", area.start, area.end); if let Some(area) = area.intersect(&physmem_limit) {