Refactor profiling code.

This commit is contained in:
4lDO2
2023-10-08 15:18:23 +02:00
parent 99ad6a0a2c
commit fac0e783ef
10 changed files with 262 additions and 210 deletions
+1 -12
View File
@@ -5,7 +5,7 @@ use core::mem;
use crate::LogicalCpuId;
use crate::paging::{RmmA, RmmArch};
use crate::percpu::{PercpuBlock, RingBuffer};
use crate::percpu::PercpuBlock;
use x86::bits64::task::TaskStateSegment;
use x86::Ring;
@@ -204,17 +204,6 @@ pub unsafe fn init_paging(stack_offset: usize, cpu_id: LogicalCpuId) {
profiling: None,
};
}
pub unsafe fn init_allocator() {
let percpu = PercpuBlock::current();
if percpu.cpu_id.get() == 4 { return }
let profiling = RingBuffer::create();
crate::scheme::debug::BUFS[percpu.cpu_id.get() as usize].store(profiling as *const _ as *mut _, core::sync::atomic::Ordering::SeqCst);
(core::ptr::addr_of!(percpu.profiling) as *mut Option<&'static RingBuffer>).write(Some(profiling));
}
#[derive(Copy, Clone, Debug)]
#[repr(packed)]
pub struct GdtEntry {
+10 -9
View File
@@ -8,6 +8,7 @@ use hashbrown::HashMap;
use x86::segmentation::Descriptor as X86IdtEntry;
use x86::dtables::{self, DescriptorTablePointer};
use crate::profiling::maybe_setup_timer;
use crate::{interrupt::*, LogicalCpuId};
use crate::interrupt::irq::{__generic_interrupts_end, __generic_interrupts_start};
use crate::ipi::IpiKind;
@@ -111,26 +112,26 @@ const fn new_idt_reservations() -> [AtomicU64; 4] {
}
/// Initialize the IDT for a
pub unsafe fn init_paging_post_heap(is_bsp: bool, cpu_id: LogicalCpuId) {
pub unsafe fn init_paging_post_heap(cpu_id: LogicalCpuId) {
let mut idts_guard = IDTS.write();
let idts_btree = idts_guard.get_or_insert_with(HashMap::new);
if is_bsp {
if cpu_id == LogicalCpuId::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);
init_generic(cpu_id, 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);
init_generic(LogicalCpuId::BSP, &mut INIT_BSP_IDT);
}
/// Initializes an IDT for any type of processor.
pub unsafe fn init_generic(is_bsp: bool, idt: &mut Idt) {
pub unsafe fn init_generic(cpu_id: LogicalCpuId, idt: &mut Idt) {
let (current_idt, current_reservations) = (&mut idt.entries, &mut idt.reservations);
let idtr: DescriptorTablePointer<X86IdtEntry> = DescriptorTablePointer {
@@ -208,7 +209,7 @@ pub unsafe fn init_generic(is_bsp: bool, idt: &mut Idt) {
// reserve bits 31:0, i.e. the first 32 interrupts, which are reserved for exceptions
*current_reservations[0].get_mut() |= 0x0000_0000_FFFF_FFFF;
if is_bsp {
if cpu_id == LogicalCpuId::BSP {
// Set up IRQs
current_idt[32].set_func(irq::pit_stack);
current_idt[33].set_func(irq::keyboard);
@@ -232,14 +233,12 @@ pub unsafe fn init_generic(is_bsp: bool, idt: &mut Idt) {
// 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 {
current_idt[32].set_func(irq::aux_timer);
// TODO: use_default_irqs! but also the legacy IRQs that are only needed on one CPU
current_idt[49].set_func(irq::lapic_error);
// reserve bit 49
*current_reservations[0].get_mut() |= 1 << 32 | 1 << 49;
*current_reservations[0].get_mut() |= 1 << 49;
}
// Set IPI handlers
current_idt[IpiKind::Wakeup as usize].set_func(ipi::wakeup);
current_idt[IpiKind::Switch as usize].set_func(ipi::switch);
@@ -256,6 +255,8 @@ pub unsafe fn init_generic(is_bsp: bool, idt: &mut Idt) {
current_idt[0x80].set_flags(IdtFlags::PRESENT | IdtFlags::RING_3 | IdtFlags::INTERRUPT);
idt.set_reserved_mut(0x80, true);
maybe_setup_timer(idt, cpu_id);
dtables::lidt(&idtr);
}
+2 -43
View File
@@ -1,9 +1,7 @@
use core::sync::atomic::Ordering;
use x86::irq::PageFaultError;
use crate::memory::GenericPfFlags;
use crate::scheme::serio::IS_PROFILING;
use crate::ptrace;
use crate::{
interrupt::stack_trace,
paging::VirtualAddress,
@@ -48,46 +46,7 @@ interrupt_stack!(debug, @paranoid, |stack| {
});
interrupt_stack!(non_maskable, @paranoid, |stack| {
let Some(profiling) = crate::percpu::PercpuBlock::current().profiling else {
return;
};
if !IS_PROFILING.load(Ordering::Relaxed) {
return;
}
if stack.iret.cs & 0b00 == 0b11 {
profiling.nmi_ucount.store(profiling.nmi_ucount.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
return;
} else if stack.iret.rflags & (1 << 9) != 0 {
// Interrupts were enabled, i.e. we were in kmain, so ignore.
return;
} else {
profiling.nmi_kcount.store(profiling.nmi_kcount.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
};
let mut buf = [0_usize; 32];
buf[0] = stack.iret.rip & !(1<<63);
buf[1] = x86::time::rdtsc() as usize;
let mut bp = stack.preserved.rbp;
let mut len = 2;
for i in 2..32 {
if bp.saturating_add(16) < crate::KERNEL_HEAP_OFFSET || bp >= crate::KERNEL_HEAP_OFFSET + crate::PML4_SIZE {
break;
}
let ip = ((bp + 8) as *const usize).read();
bp = (bp as *const usize).read();
if ip < crate::kernel_executable_offsets::__text_start() || ip >= crate::kernel_executable_offsets::__text_end() {
break;
}
buf[i] = ip;
len = i + 1;
}
let _ = profiling.extend(&buf[..len]);
crate::profiling::nmi_handler(stack);
});
interrupt_stack!(breakpoint, |stack| {
+4 -3
View File
@@ -28,8 +28,9 @@ pub fn ipi(kind: IpiKind, target: IpiTarget) {
if matches!(kind, IpiKind::Profile) {
let icr = (target as u64) << 18 | 1 << 14 | 0b100 << 8;
unsafe { LOCAL_APIC.set_icr(icr) };
} else {
let icr = (target as u64) << 18 | 1 << 14 | (kind as u64);
unsafe { LOCAL_APIC.set_icr(icr) };
return;
}
let icr = (target as u64) << 18 | 1 << 14 | (kind as u64);
unsafe { LOCAL_APIC.set_icr(icr) };
}
+5 -5
View File
@@ -6,7 +6,7 @@
use core::slice;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering, AtomicU32};
use crate::{allocator, memory, LogicalCpuId};
use crate::{allocator, memory, LogicalCpuId, profiling};
#[cfg(feature = "acpi")]
use crate::acpi;
use crate::arch::pti;
@@ -150,13 +150,13 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
// Setup kernel heap
allocator::init();
gdt::init_allocator();
profiling::init();
// Set up double buffer for grpahical debug now that heap is available
#[cfg(feature = "graphical_debug")]
graphical_debug::init_heap();
idt::init_paging_post_heap(true, LogicalCpuId::BSP);
idt::init_paging_post_heap(LogicalCpuId::BSP);
// Activate memory logging
log::init();
@@ -236,10 +236,10 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
// Set up GDT with TLS
gdt::init_paging(stack_end, cpu_id);
gdt::init_allocator();
profiling::init();
// Set up IDT for AP
idt::init_paging_post_heap(false, cpu_id);
idt::init_paging_post_heap(cpu_id);
crate::alternative::early_init(false);