debug: unify kernel logging
This commit is contained in:
parent
33fb12db59
commit
6e878c2ac1
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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) -> ! {
|
||||
|
@ -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> {
|
||||
|
@ -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!()
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()?;
|
||||
|
@ -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(())
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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!()
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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())?;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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> {
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user