diff --git a/src/acpi/madt/arch/x86.rs b/src/acpi/madt/arch/x86.rs index 45485f6d61..122a4cf741 100644 --- a/src/acpi/madt/arch/x86.rs +++ b/src/acpi/madt/arch/x86.rs @@ -8,12 +8,12 @@ use crate::{ device::local_apic::the_local_apic, start::{kstart_ap, KernelArgsAp}, }, - startup::AP_READY, cpu_set::LogicalCpuId, memory::{ allocate_p2frame, Frame, KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress, PAGE_SIZE, }, + startup::AP_READY, }; use super::{Madt, MadtEntry}; @@ -61,7 +61,6 @@ pub(super) fn init(madt: Madt) { } } - #[cfg(feature = "profiling")] unsafe { let preliminary_cpu_count = madt.iter().filter(|e| matches!(e, MadtEntry::LocalApic(entry) if u32::from(entry.id) == me.get() || entry.flags & 1 == 1)).count(); info!("Preliminary number of CPUs: {preliminary_cpu_count}"); diff --git a/src/arch/x86_shared/interrupt/exception.rs b/src/arch/x86_shared/interrupt/exception.rs index fc2aa2b2a4..7725a45d0a 100644 --- a/src/arch/x86_shared/interrupt/exception.rs +++ b/src/arch/x86_shared/interrupt/exception.rs @@ -50,10 +50,10 @@ interrupt_stack!(debug, @paranoid, |stack| { }); interrupt_stack!(non_maskable, @paranoid, |stack| { - #[cfg(feature = "profiling")] + #[cfg(target_arch = "x86_64")] unsafe { crate::profiling::nmi_handler(stack) }; - #[cfg(not(feature = "profiling"))] + #[cfg(not(all(target_arch = "x86_64", feature = "profiling")))] { // TODO: This will likely deadlock println!("Non-maskable interrupt"); diff --git a/src/profiling.rs b/src/profiling.rs index 33b1c0dfbb..79ed7fe085 100644 --- a/src/profiling.rs +++ b/src/profiling.rs @@ -1,17 +1,18 @@ -#[cfg(feature = "profiling")] -use core::sync::atomic::AtomicU32; +use alloc::{boxed::Box, vec::Vec}; use core::{ cell::{SyncUnsafeCell, UnsafeCell}, mem::size_of, - sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering}, + sync::atomic::{AtomicBool, AtomicPtr, AtomicU32, AtomicUsize, Ordering}, }; - -use alloc::{boxed::Box, vec::Vec}; +#[cfg(target_arch = "x86_64")] +use rmm::Arch; #[cfg(feature = "profiling")] +use crate::arch::{idt::Idt, interrupt::irq::aux_timer}; +#[cfg(target_arch = "x86_64")] use crate::arch::{ - idt::Idt, - interrupt::{self, irq::aux_timer, InterruptStack}, + interrupt::{self, InterruptStack}, + CurrentRmmArch, }; use crate::{ cpu_set::LogicalCpuId, @@ -19,15 +20,16 @@ use crate::{ syscall::{error::*, usercopy::UserSliceWo}, }; +#[cfg(all(feature = "profiling", not(target_arch = "x86_64")))] +compile_error!("Profiling not supported outside x86_64"); + const N: usize = 16 * 1024 * 1024; pub struct RingBuffer { head: AtomicUsize, tail: AtomicUsize, buf: &'static [UnsafeCell; N], - #[cfg_attr(not(feature = "profiling"), expect(dead_code))] pub(crate) nmi_kcount: AtomicUsize, - #[cfg_attr(not(feature = "profiling"), expect(dead_code))] pub(crate) nmi_ucount: AtomicUsize, } @@ -64,7 +66,6 @@ impl RingBuffer { [&self.buf[head..tail], &[]] } } - #[cfg_attr(not(feature = "profiling"), expect(dead_code))] pub unsafe fn extend(&self, mut slice: &[usize]) -> usize { let mut n = 0; for mut sender_slice in unsafe { self.sender_owned() } { @@ -157,8 +158,12 @@ pub fn drain_buffer(cpu_num: LogicalCpuId, buf: UserSliceWo) -> Result { } } -#[cfg(feature = "profiling")] +#[cfg(target_arch = "x86_64")] pub unsafe fn nmi_handler(stack: &InterruptStack) { + if cfg!(not(feature = "profiling")) { + return; + } + let Some(profiling) = crate::percpu::PercpuBlock::current().profiling else { return; }; @@ -184,7 +189,8 @@ pub unsafe fn nmi_handler(stack: &InterruptStack) { let mut len = 2; for i in 2..32 { - if bp < crate::PHYS_OFFSET || bp.saturating_add(16) >= crate::PHYS_OFFSET + crate::PML4_SIZE + if bp < CurrentRmmArch::PHYS_OFFSET + || bp.saturating_add(16) >= CurrentRmmArch::PHYS_OFFSET + crate::PML4_SIZE { break; } @@ -204,7 +210,6 @@ pub unsafe fn nmi_handler(stack: &InterruptStack) { let _ = unsafe { profiling.extend(&buf[..len]) }; } -#[cfg(feature = "profiling")] static NUM_ORDINARY_CPUS: AtomicU32 = AtomicU32::new(u32::MAX); #[cfg(feature = "profiling")] @@ -221,8 +226,13 @@ fn profiler_cpu() -> LogicalCpuId { } // SAFETY: must be called before any init() -#[cfg(feature = "profiling")] pub unsafe fn allocate(total_cpu_count: u32) { + if cfg!(not(feature = "profiling")) { + return; + } + + info!("Preliminary number of CPUs: {total_cpu_count}"); + let ordinary_cpu_count = total_cpu_count.checked_sub(1).unwrap(); NUM_ORDINARY_CPUS.store(ordinary_cpu_count, Ordering::SeqCst); @@ -261,19 +271,25 @@ pub unsafe fn init() { } } -#[cfg(feature = "profiling")] static ACK: AtomicU32 = AtomicU32::new(0); pub fn ready_for_profiling() { - #[cfg(feature = "profiling")] + if cfg!(not(feature = "profiling")) { + return; + } + ACK.fetch_add(1, Ordering::Relaxed); } -#[cfg(feature = "profiling")] pub fn maybe_run_profiling_helper_forever(cpu_id: LogicalCpuId) { + if cfg!(not(feature = "profiling")) { + return; + } + if cpu_id != profiler_cpu() { return; } + #[cfg(target_arch = "x86_64")] unsafe { for i in 33..255 { crate::arch::idt::IDTS @@ -302,6 +318,10 @@ pub fn maybe_run_profiling_helper_forever(cpu_id: LogicalCpuId) { #[cfg(feature = "profiling")] pub fn maybe_setup_timer(idt: &mut Idt, cpu_id: LogicalCpuId) { + if cfg!(not(feature = "profiling")) { + return; + } + if cpu_id != profiler_cpu() { return; } diff --git a/src/startup/mod.rs b/src/startup/mod.rs index 60d8c30483..8ad3cdf7f8 100644 --- a/src/startup/mod.rs +++ b/src/startup/mod.rs @@ -198,7 +198,6 @@ pub(crate) fn kmain_ap(cpu_id: crate::cpu_set::LogicalCpuId) -> ! { hint::spin_loop(); } - #[cfg(feature = "profiling")] profiling::maybe_run_profiling_helper_forever(cpu_id); if !cfg!(feature = "multi_core") {