debug: unify kernel logging

This commit is contained in:
Mark Poliakov 2024-11-30 23:51:02 +02:00
parent 33fb12db59
commit 6e878c2ac1
40 changed files with 341 additions and 387 deletions

View File

@ -107,6 +107,10 @@ impl Architecture for ArchitectureImpl {
IPI_QUEUES.init(queues);
}
fn ipi_queue(cpu_id: u32) -> Option<&'static IpiQueue<Self>> {
IPI_QUEUES.try_get().and_then(|q| q.get(cpu_id as usize))
}
fn idle_task() -> extern "C" fn(usize) -> ! {
idle_task
}
@ -115,9 +119,10 @@ impl Architecture for ArchitectureImpl {
CPU_COUNT.load(Ordering::Acquire)
}
fn local_interrupt_controller() -> &'static dyn LocalInterruptController {
let local = Self::local_cpu_data().unwrap();
*local.gic.get()
fn local_interrupt_controller() -> Option<&'static dyn LocalInterruptController> {
let local = Self::local_cpu_data()?;
let intc = *local.gic.try_get()?;
Some(intc)
}
fn message_interrupt_controller() -> &'static dyn MessageInterruptController {

View File

@ -299,7 +299,6 @@ pub(crate) unsafe fn map_device_memory(
size: usize,
attrs: DeviceMemoryAttributes,
) -> Result<RawDeviceMemoryMapping<KernelTableManagerImpl>, Error> {
// debugln!("Map {}B @ {:#x}", size, base);
let l3_aligned = base.page_align_down::<L3>();
let l3_offset = base.page_offset::<L3>();
let page_count = (l3_offset + size).page_count::<L3>();
@ -334,11 +333,6 @@ pub(crate) unsafe fn map_device_memory(
}
pub(crate) unsafe fn unmap_device_memory(map: &RawDeviceMemoryMapping<KernelTableManagerImpl>) {
// debugln!(
// "Unmap {}B @ {:#x}",
// map.page_count * map.page_size,
// map.base_address
// );
match map.page_size {
L3::SIZE => {
for i in 0..map.page_count {

View File

@ -110,8 +110,12 @@ impl Architecture for ArchitectureImpl {
unimplemented!()
}
fn local_interrupt_controller() -> &'static dyn LocalInterruptController {
unimplemented!()
fn local_interrupt_controller() -> Option<&'static dyn LocalInterruptController> {
None
}
fn ipi_queue(_cpu_id: u32) -> Option<&'static IpiQueue<Self>> {
None
}
fn idle_task() -> extern "C" fn(usize) -> ! {

View File

@ -92,14 +92,14 @@ impl<A: Architecture, S: Scheduler + 'static> CpuImpl<A, S> {
self.id
}
pub fn push_ipi_queue(_cpu_id: u32, _msg: IpiMessage) {
// XXX
todo!()
pub fn push_ipi_queue(cpu_id: u32, msg: IpiMessage) {
if let Some(queue) = A::ipi_queue(cpu_id) {
queue.push(msg);
}
}
pub fn get_ipi(&self) -> Option<IpiMessage> {
// XXX
todo!()
A::ipi_queue(self.id).and_then(|q| q.pop())
}
pub fn available_features(&self) -> Option<&A::CpuFeatures> {

View File

@ -22,7 +22,7 @@ pub const KERNEL_VIRT_OFFSET: usize = 0xC0000000;
#[cfg(any(target_pointer_width = "64", rust_analyzer))]
pub const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000;
pub trait Architecture: Sized {
pub trait Architecture: Sized + 'static {
type PerCpuData;
type CpuFeatures: CpuFeatureSet;
@ -40,6 +40,9 @@ pub trait Architecture: Sized {
///
/// Precondition: this function has not yet been called on the local CPU.
unsafe fn init_ipi_queues(queues: Vec<IpiQueue<Self>>);
fn ipi_queue(cpu_id: u32) -> Option<&'static IpiQueue<Self>>;
/// # Safety
///
/// Precondition: this function has not yet been called on the local CPU.
@ -61,7 +64,7 @@ pub trait Architecture: Sized {
fn halt() -> !;
// Architectural devices
fn local_interrupt_controller() -> &'static dyn LocalInterruptController {
fn local_interrupt_controller() -> Option<&'static dyn LocalInterruptController> {
unimplemented!()
}

View File

@ -44,9 +44,9 @@ impl<A: Architecture, T> Spinlock<A, T> {
pub fn lock(&self) -> SpinlockGuard<A, T> {
// Loop until the lock can be acquired
// if LOCK_HACK.load(Ordering::Acquire) {
// return SpinlockInnerGuard { lock: self };
// }
if LOCK_HACK.load(Ordering::Acquire) {
return SpinlockGuard { lock: self };
}
while self
.state
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
@ -75,12 +75,12 @@ impl<A: Architecture, T> DerefMut for SpinlockGuard<'_, A, T> {
impl<A: Architecture, T> Drop for SpinlockGuard<'_, A, T> {
fn drop(&mut self) {
// if !LOCK_HACK.load(Ordering::Acquire) {
self.lock
.state
.compare_exchange(true, false, Ordering::Release, Ordering::Relaxed)
.unwrap();
// }
if !LOCK_HACK.load(Ordering::Acquire) {
self.lock
.state
.compare_exchange(true, false, Ordering::Release, Ordering::Relaxed)
.unwrap();
}
}
}
@ -214,3 +214,14 @@ pub macro split_spinlock(
}
}
}
static LOCK_HACK: AtomicBool = AtomicBool::new(false);
/// "Hacks" all the locks in the kernel to make them function as "NULL"-locks instead of spinlocks.
///
/// # Safety
///
/// Only meant to be called from panic handler when the caller is sure other CPUs are halted.
pub unsafe fn hack_locks() {
LOCK_HACK.store(true, Ordering::Release);
}

View File

@ -176,9 +176,13 @@ impl Architecture for ArchitectureImpl {
}
}
fn local_interrupt_controller() -> &'static dyn LocalInterruptController {
let local = Self::local_cpu_data().unwrap();
local.local_apic
fn ipi_queue(cpu_id: u32) -> Option<&'static IpiQueue<Self>> {
IPI_QUEUES.try_get().and_then(|q| q.get(cpu_id as usize))
}
fn local_interrupt_controller() -> Option<&'static dyn LocalInterruptController> {
let cpu = Self::local_cpu_data()?;
Some(cpu.local_apic)
}
fn message_interrupt_controller() -> &'static dyn MessageInterruptController {

View File

@ -198,12 +198,6 @@ unsafe fn map_device_memory_l2(
PageEntry::<L2>::block(base.add(j * L2::SIZE), PageAttributes::WRITABLE);
}
// debugln!(
// "map l2s: base={:#x}, count={} -> {:#x}",
// base,
// count,
// DEVICE_MAPPING_OFFSET + i * L2::SIZE
// );
return Ok(DEVICE_MAPPING_OFFSET + i * L2::SIZE);
}
@ -215,7 +209,6 @@ unsafe fn map_device_memory(
size: usize,
attrs: DeviceMemoryAttributes,
) -> Result<RawDeviceMemoryMapping<KernelTableManagerImpl>, Error> {
// debugln!("Map {}B @ {:#x}", size, base);
let l3_aligned = base.page_align_down::<L3>();
let l3_offset = base.page_offset::<L3>();
let page_count = (l3_offset + size).page_count::<L3>();
@ -250,11 +243,6 @@ unsafe fn map_device_memory(
}
unsafe fn unmap_device_memory(map: &RawDeviceMemoryMapping<KernelTableManagerImpl>) {
// debugln!(
// "Unmap {}B @ {:#x}",
// map.page_count * map.page_size,
// map.base_address
// );
match map.page_size {
L3::SIZE => {
for i in 0..map.page_count {

View File

@ -41,7 +41,7 @@ register_get!(
&'static dyn MonotonicTimestampProviderDevice
);
pub fn local_interrupt_controller() -> &'static dyn LocalInterruptController {
pub fn local_interrupt_controller() -> Option<&'static dyn LocalInterruptController> {
ArchitectureImpl::local_interrupt_controller()
}

View File

@ -1,5 +1,3 @@
use core::sync::atomic::{AtomicBool, Ordering};
use kernel_arch::ArchitectureImpl;
use yggdrasil_abi::error::Error;
@ -15,8 +13,6 @@ pub type IrqGuard = kernel_arch::guard::IrqGuard<ArchitectureImpl>;
pub type Spinlock<T> = kernel_arch::sync::Spinlock<ArchitectureImpl, T>;
pub type SpinlockGuard<'a, T> = kernel_arch::sync::SpinlockGuard<'a, ArchitectureImpl, T>;
static LOCK_HACK: AtomicBool = AtomicBool::new(false);
pub trait LockMethod<'q> {
type Guard<'a>
where
@ -30,12 +26,3 @@ pub trait LockMethod<'q> {
/// Only meant to be called from Guard's [Drop] impl.
unsafe fn release(&self);
}
/// "Hacks" all the locks in the kernel to make them function as "NULL"-locks instead of spinlocks.
///
/// # Safety
///
/// Only meant to be called from panic handler when the caller is sure other CPUs are halted.
pub unsafe fn hack_locks() {
LOCK_HACK.store(true, Ordering::Release);
}

View File

@ -395,8 +395,6 @@ impl Thread {
queue.yield_cpu();
},
(false, ThreadState::Running) => {
// XXX
// debugln!("deq remote {:?}", self.id);
debug_assert!(sched.in_queue);
}
(_, ThreadState::Ready) => {

View File

@ -143,7 +143,7 @@ extern "C" fn __aarch64_ap_upper_entry() -> ! {
let cpu_id = CPU_COUNT.fetch_add(1, Ordering::SeqCst);
aarch64_cpu::asm::sev();
infoln!("cpu{} initializing", cpu_id);
log::info!("cpu{} initializing", cpu_id);
exception::init_exceptions();

View File

@ -10,13 +10,12 @@ use aarch64_cpu::{
},
};
use abi::{process::Signal, SyscallFunction};
use kernel_arch::{Architecture, ArchitectureImpl};
use kernel_arch::{sync::hack_locks, Architecture, ArchitectureImpl};
use kernel_arch_aarch64::context::ExceptionFrame;
use libk::{arch::Cpu, device::external_interrupt_controller, task::thread::Thread};
use tock_registers::interfaces::{Readable, Writeable};
use crate::{
debug::LogLevel,
mem::KERNEL_VIRT_OFFSET,
syscall::{self, raw_syscall_handler},
};
@ -37,33 +36,33 @@ fn dump_irrecoverable_exception(frame: &ExceptionFrame, ec: u64, iss: u64) {
let far = FAR_EL1.get() as usize;
let ttbr0 = TTBR0_EL1.get();
log_print_raw!(LogLevel::Fatal, "SYNC exception:\n");
log_print_raw!(LogLevel::Fatal, "FAR: {:#x}\n", far);
log_print_raw!(LogLevel::Fatal, "ELR: {:#x}\n", ELR_EL1.get());
log_print_raw!(LogLevel::Fatal, "ESR: {:#x}\n", ESR_EL1.get());
log_print_raw!(LogLevel::Fatal, "SP_EL0: {:#x}\n", SP_EL0.get());
log_print_raw!(LogLevel::Fatal, "TTBR0_EL1: {:#x}\n", ttbr0);
log_print_raw!(LogLevel::Fatal, "TTBR1_EL1: {:#x}\n", TTBR1_EL1.get());
log_print_raw!(LogLevel::Fatal, "Register dump:\n");
log_print_raw!(LogLevel::Fatal, "{:?}\n", frame);
log::error!(target: "raw", "SYNC exception:\n");
log::error!(target: "raw", "FAR: {:#x}\n", far);
log::error!(target: "raw", "ELR: {:#x}\n", ELR_EL1.get());
log::error!(target: "raw", "ESR: {:#x}\n", ESR_EL1.get());
log::error!(target: "raw", "SP_EL0: {:#x}\n", SP_EL0.get());
log::error!(target: "raw", "TTBR0_EL1: {:#x}\n", ttbr0);
log::error!(target: "raw", "TTBR1_EL1: {:#x}\n", TTBR1_EL1.get());
log::error!(target: "raw", "Register dump:\n");
log::error!(target: "raw", "{:?}\n", frame);
if let Some(cpu) = cpu {
// let current = cpu.queue().current_process();
let current = cpu.current_thread_id().and_then(Thread::get);
if let Some(current) = current {
log_print_raw!(LogLevel::Fatal, "In thread {}\n", current.id);
log::error!(target: "raw", "In thread {}\n", current.id);
let space = current.address_space();
if far < KERNEL_VIRT_OFFSET && space.as_address_with_asid() == ttbr0 {
match space.translate(far) {
Ok(phys) => log_print_raw!(
LogLevel::Fatal,
Ok(phys) => log::error!(
target: "raw",
"FAR translation: {:#x} -> {:#x}\n",
far,
phys
),
Err(_) => log_print_raw!(LogLevel::Fatal, "FAR does not translate\n"),
Err(_) => log::error!(target: "raw", "FAR does not translate\n"),
}
}
}
@ -72,7 +71,7 @@ fn dump_irrecoverable_exception(frame: &ExceptionFrame, ec: u64, iss: u64) {
match ec {
// Data abort from lower level
0b100100 => {
log_print_raw!(LogLevel::Fatal, "Exception kind: Data Abort from EL0\n");
log::error!(target: "raw", "Exception kind: Data Abort from EL0\n");
let dfsc = iss & 0x3F;
if iss & (1 << 24) != 0 {
@ -85,8 +84,8 @@ fn dump_irrecoverable_exception(frame: &ExceptionFrame, ec: u64, iss: u64) {
};
let access_type_str = if iss & (1 << 6) != 0 { "write" } else { "read" };
log_print_raw!(
LogLevel::Fatal,
log::error!(
target: "raw",
"Invalid {} of a {} to/from {:#x}\n",
access_type_str,
access_size_str,
@ -94,26 +93,26 @@ fn dump_irrecoverable_exception(frame: &ExceptionFrame, ec: u64, iss: u64) {
);
}
log_print_raw!(LogLevel::Fatal, "DFSC = {:#x}\n", dfsc);
log::error!(target: "raw", "DFSC = {:#x}\n", dfsc);
}
// Instruction abort from lower level
0b100000 => {
log_print_raw!(
LogLevel::Fatal,
log::error!(
target: "raw",
"Exception kind: Instruction Abort from EL0\n"
);
let ifsc = iss & 0x3F;
log_print_raw!(LogLevel::Fatal, "IFSC = {:#x}\n", ifsc);
log::error!(target: "raw", "IFSC = {:#x}\n", ifsc);
}
_ => (),
}
log_print_raw!(LogLevel::Fatal, "System register dump:\n");
log_print_raw!(LogLevel::Fatal, "SCTLR_EL1 = {:#x}\n", SCTLR_EL1.get());
log_print_raw!(LogLevel::Fatal, "TCR_EL1 = {:#x}\n", TCR_EL1.get());
log_print_raw!(LogLevel::Fatal, "TPIDR_EL1 = {:#x}\n", TPIDR_EL1.get());
log_print_raw!(LogLevel::Fatal, "TPIDR_EL0 = {:#x}\n", TPIDR_EL0.get());
log::error!(target: "raw", "System register dump:\n");
log::error!(target: "raw", "SCTLR_EL1 = {:#x}\n", SCTLR_EL1.get());
log::error!(target: "raw", "TCR_EL1 = {:#x}\n", TCR_EL1.get());
log::error!(target: "raw", "TPIDR_EL1 = {:#x}\n", TPIDR_EL1.get());
log::error!(target: "raw", "TPIDR_EL0 = {:#x}\n", TPIDR_EL0.get());
}
#[no_mangle]
@ -160,9 +159,7 @@ extern "C" fn __aa64_el1_sync_handler(frame: *mut ExceptionFrame) {
let ec = (esr_el1 >> 26) & 0x3F;
let iss = esr_el1 & 0x1FFFFFF;
unsafe {
libk_util::sync::hack_locks();
}
unsafe { hack_locks() };
dump_irrecoverable_exception(frame, ec, iss);
@ -221,7 +218,7 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
// BRK in AArch64
0b111100 => {
let thread = Thread::current();
warnln!(
log::warn!(
"Thread {} {:?} hit a breakpoint",
thread.id,
*thread.name.read()
@ -234,7 +231,7 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
if ec == 0b100100 {
// Data abort from lower level
let thread = Thread::current();
warnln!(
log::warn!(
"Data abort in {} {:?} at {:#x} with address {:#x}",
thread.id,
*thread.name.read(),

View File

@ -44,7 +44,7 @@ impl Gicc {
}
pub unsafe fn init(&self) {
debugln!("Enabling GICv2 GICC");
log::debug!("Enabling GICv2 GICC");
self.regs.CTLR.write(CTLR::Enable::SET);
self.regs.PMR.write(PMR::Priority.val(0xFF));
}

View File

@ -165,7 +165,7 @@ impl Gicd {
let mask = self.local_gic_target_mask();
let regs = self.shared_regs.lock();
debugln!("Enabling GICv2 GICD, max IRQ number: {}", regs.num_irqs());
log::debug!("Enabling GICv2 GICD, max IRQ number: {}", regs.num_irqs());
regs.CTLR.modify(CTLR::Enable::SET);

View File

@ -92,7 +92,7 @@ impl ExternalInterruptController for Gic {
Irq::Private(i) => i + 16,
} as usize;
debugln!(
log::debug!(
"Bound irq{} to {:?} {:?} {:?}",
index,
handler.display_name(),
@ -126,10 +126,8 @@ impl ExternalInterruptController for Gic {
if irq_number == IPI_VECTOR as usize {
gicc.clear_irq(irq_number);
// XXX
todo!();
// Cpu::local().handle_ipi();
// return;
// TODO pop entry
crate::panic::panic_secondary();
}
gicc.clear_irq(irq_number);
@ -141,7 +139,7 @@ impl ExternalInterruptController for Gic {
drop(table);
handler.handle_irq(None);
}
None => warnln!("No handler for irq{}", irq_number),
None => log::warn!("No handler for irq{}", irq_number),
}
}
}

View File

@ -5,7 +5,7 @@ use core::sync::atomic::Ordering;
use aarch64_cpu::registers::{CNTP_CTL_EL0, CNTP_TVAL_EL0};
use abi::error::Error;
use device_api::{
interrupt::{IpiDeliveryTarget, IpiMessage, Irq, LocalInterruptController},
interrupt::{Irq, LocalInterruptController},
ResetDevice,
};
use device_tree::dt::{DevTreeIndexPropExt, DevTreeNodeInfo, DeviceTree, FdtMemoryRegionIter};
@ -82,20 +82,10 @@ impl Platform for AArch64 {
unsafe fn start_application_processors(&self) {
let dt = self.dt.get();
if let Err(error) = smp::start_ap_cores(dt) {
errorln!("Could not initialize AP CPUs: {:?}", error);
log::error!("Could not initialize AP CPUs: {:?}", error);
}
}
unsafe fn send_ipi(&self, _target: IpiDeliveryTarget, _msg: IpiMessage) -> Result<(), Error> {
Ok(())
// XXX
// if let Some(local_intc) = self.lintc.try_get() {
// local_intc.send_ipi(target, msg)
// } else {
// Ok(())
// }
}
fn register_reset_device(&self, reset: &'static dyn ResetDevice) -> Result<(), Error> {
self.reset.init(reset);
Ok(())
@ -282,12 +272,12 @@ impl AArch64 {
debug::init();
infoln!(
log::info!(
"Yggdrasil v{} ({})",
env!("CARGO_PKG_VERSION"),
git_version!()
);
infoln!("Initializing aarch64 platform");
log::info!("Initializing aarch64 platform");
let nodes = dt.root().children();
if let Err(error) =
@ -308,7 +298,7 @@ impl AArch64 {
Ok(())
})
{
warnln!(
log::warn!(
"{} errors encountered when initializing platform devices",
error
);
@ -317,7 +307,7 @@ impl AArch64 {
// Initialize IRQs for the devices
device::manager_lock().devices().for_each(|dev| unsafe {
if let Err(error) = dev.init_irq() {
warnln!(
log::warn!(
"Could not init IRQs for {:?}: {:?}",
dev.display_name(),
error
@ -325,9 +315,9 @@ impl AArch64 {
}
});
infoln!("Enumerated devices:");
log::info!("Enumerated devices:");
device::manager_lock().devices().for_each(|dev| {
infoln!("* {:?}", dev.display_name());
log::info!("* {:?}", dev.display_name());
});
PciBusManager::setup_bus_devices()?;

View File

@ -57,7 +57,7 @@ impl CpuEnableMethod {
match self {
Self::Psci => {
let psci = PLATFORM.psci.try_get().ok_or_else(|| {
warnln!(
log::warn!(
"cpu{} has to be enabled through PSCI, but no PSCI found",
id
);
@ -87,21 +87,13 @@ pub unsafe fn start_ap_cores(dt: &DeviceTree) -> Result<(), Error> {
let sp = AP_TRAMPOLINE_STACK.top_addr() - KERNEL_VIRT_OFFSET;
for cpu in enumerate_cpus(dt).filter(|cpu| cpu.id != 0) {
debugln!(
log::debug!(
"cpu{}: enable-method={:?}, compatible={:?}",
cpu.id,
cpu.enable_method,
cpu.compatible
);
// const AP_STACK_PAGES: usize = 4;
// let stack_pages = phys::alloc_pages_contiguous(AP_STACK_PAGES)?;
// debugln!(
// "cpu{} stack: {:#x}..{:#x}",
// cpu.id,
// stack_pages,
// stack_pages.add(AP_STACK_PAGES * 0x1000)
// );
// Wait for the CPU to come up
let old_count = CPU_COUNT.load(Ordering::Acquire);
@ -109,7 +101,7 @@ pub unsafe fn start_ap_cores(dt: &DeviceTree) -> Result<(), Error> {
let ip = __aarch64_ap_entry as usize - KERNEL_VIRT_OFFSET;
// let sp = stack_pages.add(AP_STACK_PAGES * 0x1000);
if let Err(error) = cpu.enable_method.start_cpu(cpu.id as usize, ip, sp) {
errorln!("Couldn't start cpu{} up: {:?}", cpu.id, error);
log::error!("Couldn't start cpu{} up: {:?}", cpu.id, error);
continue;
}
@ -117,7 +109,7 @@ pub unsafe fn start_ap_cores(dt: &DeviceTree) -> Result<(), Error> {
aarch64_cpu::asm::wfe();
}
debugln!("cpu{} is up", cpu.id);
log::debug!("cpu{} is up", cpu.id);
}
Ok(())

View File

@ -152,24 +152,24 @@ static IDT: IrqSafeRwLock<[Entry; SIZE]> = IrqSafeRwLock::new([Entry::NULL; SIZE
fn dump_user_exception(kind: ExceptionKind, frame: &ExceptionFrame) {
let thread = Thread::current();
warnln!("{:?} in {} ({:?})", kind, thread.id, *thread.name.read());
warnln!("ip = {:02x}:{:08x}", frame.cs, frame.eip);
warnln!("sp = {:02x}:{:08x}", frame.ss, frame.esp);
warnln!("cr3 = {:#010x}", CR3.get());
log::warn!("{:?} in {} ({:?})", kind, thread.id, *thread.name.read());
log::warn!("ip = {:02x}:{:08x}", frame.cs, frame.eip);
log::warn!("sp = {:02x}:{:08x}", frame.ss, frame.esp);
log::warn!("cr3 = {:#010x}", CR3.get());
if kind == ExceptionKind::PageFault {
warnln!("cr2 = {:#010x}", CR2.get());
log::warn!("cr2 = {:#010x}", CR2.get());
}
}
fn kernel_exception_inner(kind: ExceptionKind, frame: &ExceptionFrame) -> ! {
let cr3 = CR3.get();
fatalln!("{:?} in KERNEL, frame {:p}, cr3 = {:#x}", kind, frame, cr3);
log::error!("{:?} in KERNEL, frame {:p}, cr3 = {:#x}", kind, frame, cr3);
if kind == ExceptionKind::PageFault {
let cr2 = CR2.get();
fatalln!("cr2 = {:#x}", cr2);
log::error!("cr2 = {:#x}", cr2);
}
fatalln!("CS:EIP = {:02x}:{:08x}", frame.cs, frame.eip);
log::error!("CS:EIP = {:02x}:{:08x}", frame.cs, frame.eip);
panic!("Irrecoverable exception")
}

View File

@ -87,8 +87,8 @@ impl Platform for I686 {
ArchitectureImpl::halt();
}
unsafe fn send_ipi(&self, _target: IpiDeliveryTarget, _msg: IpiMessage) -> Result<(), Error> {
Ok(())
unsafe fn send_ipi(&self, _target: IpiDeliveryTarget, _msg: IpiMessage) -> Result<bool, Error> {
Ok(false)
}
unsafe fn start_application_processors(&self) {
@ -103,7 +103,7 @@ impl Platform for I686 {
impl I686 {
fn init_initrd(initrd_start: PhysicalAddress, initrd_end: PhysicalAddress) {
if initrd_start.is_zero() || initrd_end <= initrd_start {
infoln!("No initrd loaded");
log::info!("No initrd loaded");
return;
}
@ -241,7 +241,7 @@ impl I686 {
device::register_device(&PS2);
infoln!(
log::info!(
"Yggdrasil v{} ({})",
env!("CARGO_PKG_VERSION"),
git_version!()

View File

@ -68,8 +68,13 @@ pub trait Platform {
/// # Safety
///
/// As the call may alter the flow of execution on CPUs, this function is unsafe.
unsafe fn send_ipi(&self, target: IpiDeliveryTarget, msg: IpiMessage) -> Result<(), Error> {
Ok(())
unsafe fn send_ipi(&self, target: IpiDeliveryTarget, msg: IpiMessage) -> Result<bool, Error> {
if let Some(intc) = ArchitectureImpl::local_interrupt_controller() {
intc.send_ipi(target, msg).map(|_| true)
} else {
log::debug!("No local interrupt controller -> no IPI");
Ok(false)
}
}
/// Performs a CPU reset.

View File

@ -118,7 +118,7 @@ impl I8259 {
pub fn disable(&self) {
let inner = self.inner.lock();
infoln!("Disabling i8259 PIC");
log::info!("Disabling i8259 PIC");
// Remap PIC IRQ vectors to 32..
inner.master_cmd.write(ICW1_INIT | ICW1_ICW4);

View File

@ -170,7 +170,7 @@ impl acpi_system::Handler for AcpiHandlerImpl {
}
fn install_interrupt_handler(irq: u32) -> Result<(), AcpiSystemError> {
infoln!("Installing ACPI SCI handler at IRQ #{}", irq);
log::info!("Installing ACPI SCI handler at IRQ #{}", irq);
let intc = external_interrupt_controller();
let handler = Box::leak(Box::new(SciHandler));

View File

@ -86,7 +86,7 @@ impl Inner {
assert!(gsi < self.max_gsi);
assert!(vector < 0x100);
infoln!("map_irq gsi{}, vec{}, apic{}", gsi, vector, apic_id);
log::info!("map_irq gsi{}, vec{}, apic{}", gsi, vector, apic_id);
let mut low = self.regs.read(REG_REDIRECTION_BASE + gsi * 2);
let mut high = self.regs.read(REG_REDIRECTION_BASE + gsi * 2 + 1);
@ -142,7 +142,7 @@ impl Inner {
let low = self.regs.read(REG_REDIRECTION_BASE + gsi * 2);
if enabled {
debugln!("Unmask GSI #{}", gsi);
log::debug!("Unmask GSI #{}", gsi);
self.regs
.write(REG_REDIRECTION_BASE + gsi * 2, low & !ENTRY_LOW_MASK)
} else {
@ -175,7 +175,7 @@ impl ExternalInterruptController for IoApic {
let gsi_target_vector = (table_vector as u32) + IO_APIC_VECTOR_OFFSET;
let bsp_apic = *BSP_APIC_ID.get();
infoln!(
log::info!(
"Binding {:?} ({}) to {}:{}",
irq,
handler.display_name(),
@ -221,7 +221,7 @@ impl ExternalInterruptController for IoApic {
if let Some(handler) = table.handler(gsi) {
handler.handle_irq(None);
} else {
warnln!("No handler set for GSI #{}", gsi);
log::warn!("No handler set for GSI #{}", gsi);
}
}
}
@ -230,11 +230,13 @@ impl IoApic {
/// Creates an I/O APIC instance from its ACPI definition
pub fn from_acpi(info: &AcpiApic<AcpiAllocator>) -> Result<Self, Error> {
if info.io_apics.len() != 1 {
warnln!("The system has multiple I/O APICs, but the kernel only knows how to use one");
log::warn!(
"The system has multiple I/O APICs, but the kernel only knows how to use one"
);
}
let ioapic = info.io_apics.first().unwrap();
infoln!("I/O APIC at {:#x}", ioapic.address);
log::info!("I/O APIC at {:#x}", ioapic.address);
let mut isa_redirections = [None; 16];
@ -259,7 +261,7 @@ impl IoApic {
Polarity::ActiveHigh => IrqLevel::ActiveHigh,
};
debugln!(
log::debug!(
"ISA IRQ #{} -> GSI #{}",
index,
redir.global_system_interrupt
@ -280,7 +282,7 @@ impl IoApic {
let max_gsi = (regs.read(REG_IOAPIC_VERSION) >> 16) & 0xFF;
infoln!("Maximum GSI number: {}", max_gsi);
log::info!("Maximum GSI number: {}", max_gsi);
let mut inner = Inner { regs, max_gsi };

View File

@ -156,7 +156,7 @@ impl LocalApicInterface for LocalApic {
}
unsafe fn wakeup_cpu(&self, apic_id: u32, entry_vector: PhysicalAddress) {
infoln!("Waking up apic{}, entry = {:#x}", apic_id, entry_vector);
log::info!("Waking up apic{}, entry = {:#x}", apic_id, entry_vector);
while self.regs.ICR0.matches_all(ICR0::DeliveryStatus::SET) {
core::hint::spin_loop();
@ -242,7 +242,7 @@ impl MessageInterruptController for LocalApic {
row.push(handler);
infoln!(
log::info!(
"Bind {}:{} -> apic{}:msi{}",
handler.display_name(),
i,

View File

@ -4,14 +4,12 @@ use core::{arch::global_asm, mem::size_of};
use abi::{primitive_enum, process::Signal};
use kernel_arch_x86::registers::{CR2, CR3};
use kernel_arch_x86_64::context::ExceptionFrame;
use libk::{arch::Cpu, task::thread::Thread};
use libk::task::thread::Thread;
use libk_util::sync::spin_rwlock::IrqSafeRwLock;
use tock_registers::interfaces::Readable;
use crate::arch::x86_64::apic;
use super::PLATFORM;
primitive_enum! {
enum ExceptionKind: u64 {
DivisionError = 0,
@ -116,11 +114,11 @@ static IDT: IrqSafeRwLock<[Entry; SIZE]> = IrqSafeRwLock::new([Entry::NULL; SIZE
fn dump_user_exception(kind: ExceptionKind, frame: &ExceptionFrame) {
let thread = Thread::current();
warnln!("{:?} in {} ({:?})", kind, thread.id, *thread.name.read());
warnln!("ip = {:02x}:{:08x}", frame.cs, frame.rip);
warnln!("cr3 = {:#010x}", CR3.get());
log::warn!("{:?} in {} ({:?})", kind, thread.id, *thread.name.read());
log::warn!("ip = {:02x}:{:08x}", frame.cs, frame.rip);
log::warn!("cr3 = {:#010x}", CR3.get());
if kind == ExceptionKind::PageFault {
warnln!("cr2 = {:#010x}", CR2.get());
log::warn!("cr2 = {:#010x}", CR2.get());
}
}
@ -179,11 +177,11 @@ fn user_exception_inner(kind: ExceptionKind, frame: &mut ExceptionFrame) {
fn kernel_exception_inner(kind: ExceptionKind, frame: &ExceptionFrame) -> ! {
let cr3 = CR3.get();
fatalln!("{:?} in KERNEL, frame {:p}, cr3 = {:#x}", kind, frame, cr3);
log::error!("{:?} in KERNEL, frame {:p}, cr3 = {:#x}", kind, frame, cr3);
if kind == ExceptionKind::PageFault {
let cr2 = CR2.get();
fatalln!("cr2 = {:#x}", cr2);
log::error!("cr2 = {:#x}", cr2);
}
// XXX
@ -203,20 +201,14 @@ extern "C" fn __x86_64_exception_handler(frame: *mut ExceptionFrame) {
Thread::current().handle_pending_signals(frame);
}
} else {
if kind == ExceptionKind::NonMaskableInterrupt {
let cpu = Cpu::local();
if let Some(msg) = cpu.get_ipi() {
unsafe {
PLATFORM.handle_ipi(msg);
}
}
}
kernel_exception_inner(kind, frame)
}
}
extern "C" fn __x86_64_nmi_handler() -> ! {
crate::panic::panic_secondary();
}
/// Initializes the interrupt descriptor table for the given CPU.
///
/// # Safety
@ -248,5 +240,6 @@ pub unsafe fn init_exceptions(cpu_index: usize) {
global_asm!(
include_str!("vectors.S"),
exception_handler = sym __x86_64_exception_handler,
nmi_handler = sym __x86_64_nmi_handler,
options(att_syntax)
);

View File

@ -45,7 +45,6 @@ use crate::{
display::{console, fb_console::FramebufferConsole, linear_fb::LinearFramebuffer},
},
fs::{Initrd, INITRD_DATA},
panic::panic_secondary,
};
use self::{
@ -54,7 +53,7 @@ use self::{
boot::BootData,
};
use super::{x86::intrinsics, IpiMessage, Platform};
use super::{x86::intrinsics, Platform};
/// Offset where legacy ISA IRQs are remapped
pub const ISA_IRQ_OFFSET: u32 = apic::ioapic::ISA_IRQ_OFFSET;
@ -100,13 +99,6 @@ impl Platform for X86_64 {
}
impl X86_64 {
unsafe fn handle_ipi(&self, msg: IpiMessage) {
match msg {
IpiMessage::Panic => panic_secondary(),
IpiMessage::Shutdown => unimplemented!("TODO: ACPI shutdown"),
}
}
fn set_boot_data(&self, data: BootData) {
match data {
BootData::YBoot(data) => {
@ -341,7 +333,7 @@ impl X86_64 {
debug::init();
infoln!(
log::info!(
"Yggdrasil v{} ({})",
env!("CARGO_PKG_VERSION"),
git_version!()
@ -373,7 +365,7 @@ impl X86_64 {
unsafe fn init_acpi_from_rsdp(&self, rsdp: usize) -> Result<(), Error> {
let acpi_tables = AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp).map_err(|err| {
errorln!("Could not initialize ACPI tables: {:?}", err);
log::error!("Could not initialize ACPI tables: {:?}", err);
Error::InvalidArgument
})?;
self.acpi.init(acpi_tables);
@ -385,7 +377,7 @@ impl X86_64 {
acpi: &'static AcpiTables<AcpiHandlerImpl>,
) -> Result<(), Error> {
let platform_info = acpi.platform_info_in(AcpiAllocator).map_err(|err| {
errorln!("Could not get ACPI platform info: {:?}", err);
log::error!("Could not get ACPI platform info: {:?}", err);
Error::InvalidArgument
})?;
@ -440,7 +432,7 @@ impl X86_64 {
fn init_initrd(initrd_start: PhysicalAddress, initrd_end: PhysicalAddress) {
if initrd_start.is_zero() || initrd_end <= initrd_start {
infoln!("No initrd loaded");
log::info!("No initrd loaded");
return;
}

View File

@ -70,7 +70,7 @@ unsafe fn start_ap_core(apic_id: u32) {
core::hint::spin_loop();
}
infoln!("cpu{} up", cpu_count);
log::info!("cpu{} up", cpu_count);
}
/// Starts up application processors specified by ACPI MADT.

View File

@ -102,7 +102,7 @@ __x86_64_exc_common:
ISR_NERR 0
ISR_NERR 1
ISR_NERR 2
// ISR_NERR 2
ISR_NERR 3
ISR_NERR 4
ISR_NERR 5
@ -133,6 +133,11 @@ ISR_NERR 29
ISR_YERR 30
ISR_NERR 31
// Special handler for NMI
__x86_64_exc_2:
cli
jmp {nmi_handler}
.section .rodata
.global __x86_64_exception_vectors
.p2align 4

View File

@ -5,15 +5,23 @@ use core::{
};
use abi::error::Error;
use libk::task::process::Process;
use libk_util::{ring::RingBuffer, sync::IrqSafeSpinlock, StaticVector};
use libk::task::{process::Process, thread::Thread};
use libk_util::{
ring::RingBuffer,
sync::{IrqSafeSpinlock, IrqSafeSpinlockGuard},
StaticVector,
};
const MAX_DEBUG_SINKS: usize = 4;
const RING_LOGGER_CAPACITY: usize = 65536;
static RING_AVAILABLE: AtomicBool = AtomicBool::new(false);
struct SimpleLogger;
struct KernelLoggerSink;
/// Locking log sink for dumping panic info
pub struct PanicLoggerSink<'a> {
lock: IrqSafeSpinlockGuard<'a, StaticVector<DebugSinkWrapper, MAX_DEBUG_SINKS>>,
}
struct RingLoggerInner {
data: RingBuffer<u8>,
@ -60,73 +68,86 @@ pub trait DebugSink: Sync {
}
}
macro_rules! log_print_raw {
($level:expr, $($args:tt)+) => {
$crate::debug::debug_internal(format_args!($($args)+), $level)
};
}
macro_rules! log_print {
($level:expr, $($args:tt)+) => {
log_print_raw!($level, "cpu{}:{}:{}: {}", libk::task::cpu_index(), file!(), line!(), format_args!($($args)+))
};
}
macro_rules! debug_tpl {
($d:tt $name:ident, $nameln:ident, $level:ident) => {
#[allow(unused_macros)]
/// Prints the message to the log
macro_rules! $name {
($d($d args:tt)+) => (log_print!($crate::debug::LogLevel::$level, $d($d args)+));
}
/// Prints the message to the log, terminated by a newline character
#[allow(unused_macros)]
macro_rules! $nameln {
() => {
$name!("\n")
};
($d($d args:tt)+) => ($name!("{}\n", format_args!($d($d args)+)));
}
};
}
debug_tpl!($ debug, debugln, Debug);
debug_tpl!($ info, infoln, Info);
debug_tpl!($ warn, warnln, Warning);
debug_tpl!($ error, errorln, Error);
debug_tpl!($ fatal, fatalln, Fatal);
#[derive(Clone, Copy)]
struct DebugSinkWrapper {
inner: &'static dyn DebugSink,
level: LogLevel,
}
impl log::Log for SimpleLogger {
struct SinkWriter {
sink: &'static dyn DebugSink,
}
impl fmt::Write for SinkWriter {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.sink.puts(s).map_err(|_| fmt::Error)
}
}
impl log::Log for DebugSinkWrapper {
fn enabled(&self, metadata: &log::Metadata) -> bool {
LogLevel::from(metadata.level()) >= self.level
}
fn log(&self, record: &log::Record) {
use core::fmt::Write;
let level = LogLevel::from(record.level());
let file = record.file().unwrap_or("<???>");
let line = record.line().unwrap_or(0);
let args = record.args();
let (prefix, suffix) = if self.inner.supports_control_sequences() {
(level.log_prefix(), level.log_suffix())
} else {
("", "")
};
let mut writer = SinkWriter { sink: self.inner };
match record.target() {
"program" => {
write!(writer, "{args}").ok();
}
"raw" => {
write!(writer, "{prefix}{args}{suffix}").ok();
}
_ => {
writeln!(writer, "{prefix}{file}:{line}: {args}{suffix}").ok();
}
}
}
fn flush(&self) {}
}
impl log::Log for RingLoggerSink {
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.target() != "program"
}
fn log(&self, record: &log::Record) {
use fmt::Write;
let mut lock = self.inner.lock();
let file = record.file().unwrap_or("<???>");
let line = record.line().unwrap_or(0);
writeln!(lock, "{}:{}: {}", file, line, record.args()).ok();
}
fn flush(&self) {}
}
impl log::Log for KernelLoggerSink {
fn enabled(&self, _metadata: &log::Metadata) -> bool {
true
}
fn log(&self, record: &log::Record) {
let file = record.file().unwrap_or("<???>");
let line = record.line().unwrap_or(0);
match record.level() {
log::Level::Error => {
log_print_raw!(LogLevel::Error, "{}:{}: {}\n", file, line, record.args())
}
log::Level::Warn => {
log_print_raw!(LogLevel::Warning, "{}:{}: {}\n", file, line, record.args())
} // warnln!("{}", record.args()),
log::Level::Info => {
log_print_raw!(LogLevel::Info, "{}:{}: {}\n", file, line, record.args())
}
log::Level::Debug => {
log_print_raw!(LogLevel::Debug, "{}:{}: {}\n", file, line, record.args())
}
log::Level::Trace => {
log_print_raw!(LogLevel::Trace, "{}:{}: {}\n", file, line, record.args())
if RING_AVAILABLE.load(Ordering::Acquire) {
RING_LOGGER_SINK.log(record);
}
for sink in DEBUG_SINKS.lock().iter_mut() {
if sink.enabled(record.metadata()) {
sink.log(record);
}
}
}
@ -158,13 +179,6 @@ impl LogLevel {
}
}
impl fmt::Write for DebugSinkWrapper {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.inner.puts(s).ok();
Ok(())
}
}
impl RingLoggerSink {
const fn new() -> Self {
Self {
@ -179,11 +193,6 @@ impl RingLoggerSink {
unsafe { self.inner.lock().data.read_all_static(pos, buffer) }
}
fn write_fmt(&self, args: fmt::Arguments<'_>) -> fmt::Result {
use fmt::Write;
self.inner.lock().write_fmt(args)
}
fn init_buffer(&self) -> Result<(), Error> {
self.inner.lock().data.reserve()
}
@ -198,7 +207,63 @@ impl fmt::Write for RingLoggerInner {
}
}
static LOGGER: SimpleLogger = SimpleLogger;
impl From<log::Level> for LogLevel {
fn from(value: log::Level) -> Self {
match value {
log::Level::Trace => Self::Trace,
log::Level::Debug => Self::Debug,
log::Level::Info => Self::Info,
log::Level::Warn => Self::Warning,
log::Level::Error => Self::Error,
}
}
}
impl PanicLoggerSink<'_> {
/// Locks the global logger, allowing the panicking CPU to dump its panic info without being
/// interrupted
pub fn lock() -> Self {
Self {
lock: DEBUG_SINKS.lock(),
}
}
/// Prints a formatted message to the panic log
pub fn log_fmt(&self, args: Arguments) {
use log::Log;
self.log(
&log::Record::builder()
.level(log::Level::Error)
.target("raw")
.args(args)
.build(),
)
}
}
impl log::Log for PanicLoggerSink<'_> {
fn enabled(&self, _metadata: &log::Metadata) -> bool {
true
}
fn log(&self, record: &log::Record) {
for sink in self.lock.iter() {
if sink.enabled(record.metadata()) {
sink.log(record);
}
}
}
fn flush(&self) {}
}
/// Logs a formatted message to the panic output
pub macro panic_log($sink:expr, $($args:tt)+) {
$sink.log_fmt(format_args!($($args)+))
}
static LOGGER: KernelLoggerSink = KernelLoggerSink;
static DEBUG_SINKS: IrqSafeSpinlock<StaticVector<DebugSinkWrapper, MAX_DEBUG_SINKS>> =
IrqSafeSpinlock::new(StaticVector::new());
@ -206,41 +271,6 @@ static DEBUG_SINKS: IrqSafeSpinlock<StaticVector<DebugSinkWrapper, MAX_DEBUG_SIN
/// See [RingLoggerSink]
pub static RING_LOGGER_SINK: RingLoggerSink = RingLoggerSink::new();
/// Prints a hex-dump of a slice, appending a virtual address offset to the output
pub fn hex_dump(level: LogLevel, addr_offset: usize, data: &[u8]) {
const WINDOW_SIZE: usize = 16;
let window_count = (data.len() + WINDOW_SIZE) / WINDOW_SIZE;
for iw in 0..window_count {
let off = iw * WINDOW_SIZE;
let len = core::cmp::min(data.len() - off, WINDOW_SIZE);
let window = &data[off..off + len];
log_print_raw!(level, "{:04X}: ", addr_offset + off);
for i in 0..WINDOW_SIZE {
if i < window.len() {
log_print_raw!(level, "{:02X}", window[i]);
} else {
log_print_raw!(level, " ");
}
if i % 2 == 1 {
log_print_raw!(level, " ");
}
}
for &ch in window {
if ch.is_ascii_graphic() || ch == b' ' {
log_print_raw!(level, "{}", ch as char);
} else {
log_print_raw!(level, ".");
}
}
log_print_raw!(level, "\n");
}
}
/// Adds a debugging output sink
pub fn add_sink(sink: &'static dyn DebugSink, level: LogLevel) {
DEBUG_SINKS
@ -249,13 +279,13 @@ pub fn add_sink(sink: &'static dyn DebugSink, level: LogLevel) {
}
/// Print a trace message coming from a process
pub fn program_trace(process: &Process, message: &str) {
log_print_raw!(
LogLevel::Trace,
"[trace {} {:?}] {}\n",
pub fn program_trace(process: &Process, thread: &Thread, message: &str) {
log::debug!(
target: "program",
"[trace {}:{}:{:?}] {message}\n",
process.id,
process.name,
message
thread.id,
*thread.name.read()
);
}
@ -268,31 +298,4 @@ pub fn init() {
log::set_logger(&LOGGER)
.map(|_| log::set_max_level(log::LevelFilter::Trace))
.ok();
log_print_raw!(LogLevel::Info, "\x1b[0m");
}
#[doc(hidden)]
pub fn debug_internal(args: Arguments, level: LogLevel) {
use fmt::Write;
if RING_AVAILABLE.load(Ordering::Acquire) {
RING_LOGGER_SINK.write_fmt(args).ok();
}
for sink in DEBUG_SINKS.lock().iter_mut() {
if level < sink.level {
continue;
}
if sink.inner.supports_control_sequences() {
sink.write_str(level.log_prefix()).ok();
}
sink.write_fmt(args).ok();
if sink.inner.supports_control_sequences() {
sink.write_str(level.log_suffix()).ok();
}
}
}

View File

@ -131,7 +131,7 @@ impl PageProvider for LinearFramebuffer {
fn get_page(&self, offset: u64) -> Result<PhysicalAddress, Error> {
let offset = offset as usize;
if offset + L3::SIZE > self.size {
warnln!(
log::warn!(
"Tried to map offset {:#x}, but size is {:#x}",
offset,
self.size

View File

@ -14,7 +14,7 @@ static DEVICE_MANAGER: IrqSafeSpinlock<DeviceManager> = IrqSafeSpinlock::new(Dev
/// Adds a device to the kernel's device table and returns the ID assigned to it
pub fn register_device(device: &'static dyn Device) -> DeviceId {
debugln!("Register {:?}", device.display_name());
log::debug!("Register {:?}", device.display_name());
DEVICE_MANAGER.lock().register(device)
}

View File

@ -28,7 +28,7 @@ fn setup_root() -> Result<NodeRef, Error> {
/// This function is meant to be used as a kernel-space process after all the platform-specific
/// initialization has finished.
pub fn kinit() -> Result<(), Error> {
infoln!("In main");
log::info!("In main");
runtime::spawn(ygg_driver_usb::bus::bus_handler())?;

View File

@ -20,7 +20,8 @@
exact_size_is_empty,
maybe_uninit_uninit_array,
const_maybe_uninit_uninit_array,
never_type
never_type,
format_args_nl
)]
#![allow(
clippy::new_without_default,
@ -106,7 +107,7 @@ pub fn kernel_main() -> ! {
spawn_kernel_closure("[kinit]", init::kinit).expect("Could not spawn [kinit]");
infoln!("All cpus ready");
log::info!("All cpus ready");
unsafe {
task::enter();

View File

@ -2,13 +2,13 @@
use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
use device_api::interrupt::{IpiDeliveryTarget, IpiMessage};
use kernel_arch::{Architecture, ArchitectureImpl};
use libk::arch::Cpu;
use libk_util::sync::{hack_locks, SpinFence};
use kernel_arch::{sync::hack_locks, Architecture, ArchitectureImpl};
use libk::arch::{Cpu, LocalCpu};
use libk_util::sync::SpinFence;
use crate::{
arch::{Platform, PLATFORM},
debug::LogLevel,
debug::{self, PanicLoggerSink},
device::display::console::flush_consoles,
};
@ -30,7 +30,7 @@ pub fn panic_secondary() -> ! {
core::hint::spin_loop();
}
log_print_raw!(LogLevel::Fatal, "X");
log::error!(target: "raw", "X");
flush_consoles();
PANIC_SEQUENCE.fetch_add(1, Ordering::Release);
@ -40,58 +40,51 @@ pub fn panic_secondary() -> ! {
}
}
fn dump_panic_info(cpu: &LocalCpu, pi: &core::panic::PanicInfo) {
let sink = PanicLoggerSink::lock();
debug::panic_log!(sink, "--- BEGIN PANIC ---\n");
debug::panic_log!(sink, "In CPU {}\n", cpu.id());
debug::panic_log!(sink, "Kernel panic");
if let Some(location) = pi.location() {
debug::panic_log!(sink, " ar {}:{}:\n", location.file(), location.line());
} else {
debug::panic_log!(sink, ":\n");
}
debug::panic_log!(sink, "\n{}\n", pi.message());
debug::panic_log!(sink, "--- END PANIC ---\n");
}
pub(crate) fn panic_handler(pi: &core::panic::PanicInfo) -> ! {
let cpu = Cpu::local();
static PANIC_HAPPENED: AtomicBool = AtomicBool::new(false);
fatalln!("panic_handler({:?})", pi);
if PANIC_HAPPENED
.compare_exchange(false, true, Ordering::Release, Ordering::Acquire)
.is_ok()
{
// Let other CPUs know we're screwed
unsafe {
if unsafe {
PLATFORM
.send_ipi(IpiDeliveryTarget::OtherCpus, IpiMessage::Panic)
.ok();
.unwrap_or(false)
} {
let ap_count = ArchitectureImpl::cpu_count() - 1;
PANIC_HANDLED_FENCE.wait_all(ap_count);
}
let ap_count = ArchitectureImpl::cpu_count() - 1;
PANIC_HANDLED_FENCE.wait_all(ap_count);
unsafe { hack_locks() };
unsafe {
hack_locks();
}
log_print_raw!(LogLevel::Fatal, "--- BEGIN PANIC ---\n");
log_print_raw!(LogLevel::Fatal, "In CPU {}\n", cpu.id());
log_print_raw!(LogLevel::Fatal, "Kernel panic ");
if let Some(location) = pi.location() {
log_print_raw!(
LogLevel::Fatal,
"at {}:{}:",
location.file(),
location.line()
);
} else {
log_print_raw!(LogLevel::Fatal, ":");
}
log_print_raw!(LogLevel::Fatal, "\n");
log_print_raw!(LogLevel::Fatal, "{}\n", pi.message());
log_print_raw!(LogLevel::Fatal, "--- END PANIC ---\n");
dump_panic_info(&cpu, pi);
PANIC_FINISHED_FENCE.signal();
while PANIC_SEQUENCE.load(Ordering::Acquire) != cpu.id() {
core::hint::spin_loop();
}
log_print_raw!(LogLevel::Fatal, "X");
log::error!(target: "raw", "X");
flush_consoles();

View File

@ -19,7 +19,7 @@ pub fn ref_mut<'a, T: Sized>(addr: usize) -> Result<&'a mut T, Error> {
pub fn str_ref<'a>(base: usize, len: usize) -> Result<&'a str, Error> {
let slice = slice_ref(base, len)?;
if slice.contains(&0) {
warnln!("User-supplied string contains NUL characters");
log::warn!("User-supplied string contains NUL characters");
return Err(Error::InvalidArgument);
}
Ok(core::str::from_utf8(slice).unwrap())

View File

@ -1,19 +1,13 @@
use abi::{debug::DebugOperation, error::Error, process::ProcessId};
use libk::task::{process::Process, thread::Thread};
use crate::debug::LogLevel;
use crate::debug;
pub(crate) fn debug_trace(message: &str) {
let thread = Thread::current();
let process = thread.process();
log_print_raw!(
LogLevel::Debug,
"[{}:{}] TRACE: {}\n",
process.id,
thread.id,
message
);
debug::program_trace(&process, &thread, message);
}
pub(crate) fn debug_control(pid: ProcessId, op: &mut DebugOperation) -> Result<(), Error> {

View File

@ -36,7 +36,7 @@ pub(crate) fn open(
&& let Some(node) = file.node()
&& node.is_terminal()
{
debugln!("Session terminal set for #{}: {}", process.id, path);
log::debug!("Session terminal set for #{}: {}", process.id, path);
process.set_session_terminal(node.clone());
}
@ -55,7 +55,7 @@ pub(crate) fn close(fd: RawFd) -> Result<(), Error> {
let res = io.files.close_file(fd);
if res == Err(Error::InvalidFile) {
warnln!("Double close of fd {:?} in process {}", fd, process.id);
log::warn!("Double close of fd {:?} in process {}", fd, process.id);
}
res

View File

@ -160,7 +160,7 @@ pub(crate) fn spawn_process(options: &SpawnOptions<'_>) -> Result<ProcessId, Err
None
}
}) {
debugln!("{} requested terminal {:?}", pid, fd);
log::debug!("{} requested terminal {:?}", pid, fd);
let file = child_io.files.file(fd)?;
// let node = file.node().ok_or(Error::InvalidFile)?;
let mut req = DeviceRequest::SetTerminalGroup(child_process.group_id());

View File

@ -47,11 +47,6 @@ pub unsafe fn handle_signal_exit<F: TaskFrame>(frame: &mut F) {
todo!("Invalid SignalEntryData pointer: {:?}", err)
}
};
// infoln!(
// "Handling signal exit to ip={:#x}, sp={:#x}",
// saved_data.frame.user_ip,
// saved_data.frame.user_sp
// );
frame.restore(&saved_data.frame);
}